1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Corporation code.
16 : *
17 : * The Initial Developer of the Original Code is Oracle Corporation.
18 : * Portions created by the Initial Developer are Copyright (C) 2005
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Bas Schouten <bschouten@mozilla.com>
23 : * Matt Woodrow <mwoodrow@mozilla.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef GFX_3DMATRIX_H
40 : #define GFX_3DMATRIX_H
41 :
42 : #include <gfxTypes.h>
43 : #include <gfxPoint3D.h>
44 : #include <gfxPointH3D.h>
45 : #include <gfxMatrix.h>
46 : #include <gfxQuad.h>
47 :
48 : /**
49 : * This class represents a 3D transformation. The matrix is laid
50 : * out as follows:
51 : *
52 : * _11 _12 _13 _14
53 : * _21 _22 _23 _24
54 : * _31 _32 _33 _34
55 : * _41 _42 _43 _44
56 : *
57 : * This matrix is treated as row-major. Assuming we consider our vectors row
58 : * vectors, this matrix type will be identical in memory to the OpenGL and D3D
59 : * matrices. OpenGL matrices are column-major, however OpenGL also treats
60 : * vectors as column vectors, the double transposition makes everything work
61 : * out nicely.
62 : */
63 : class THEBES_API gfx3DMatrix
64 : {
65 : public:
66 : /**
67 : * Create matrix.
68 : */
69 : gfx3DMatrix(void);
70 :
71 : /**
72 : * Matrix multiplication.
73 : */
74 : gfx3DMatrix operator*(const gfx3DMatrix &aMatrix) const;
75 : gfx3DMatrix& operator*=(const gfx3DMatrix &aMatrix);
76 :
77 0 : gfxPointH3D& operator[](int aIndex)
78 : {
79 0 : NS_ABORT_IF_FALSE(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
80 0 : return *reinterpret_cast<gfxPointH3D*>((&_11)+4*aIndex);
81 : }
82 0 : const gfxPointH3D& operator[](int aIndex) const
83 : {
84 0 : NS_ABORT_IF_FALSE(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
85 0 : return *reinterpret_cast<const gfxPointH3D*>((&_11)+4*aIndex);
86 : }
87 :
88 : /**
89 : * Return true if this matrix and |aMatrix| are the same matrix.
90 : */
91 : bool operator==(const gfx3DMatrix& aMatrix) const;
92 :
93 : /**
94 : * Divide all values in the matrix by a scalar value
95 : */
96 : gfx3DMatrix& operator/=(gfxFloat scalar);
97 :
98 : /**
99 : * Create a 3D matrix from a gfxMatrix 2D affine transformation.
100 : *
101 : * \param aMatrix gfxMatrix 2D affine transformation.
102 : */
103 : static gfx3DMatrix From2D(const gfxMatrix &aMatrix);
104 :
105 : /**
106 : * Returns true if the matrix is isomorphic to a 2D affine transformation
107 : * (i.e. as obtained by From2D). If it is, optionally returns the 2D
108 : * matrix in aMatrix.
109 : */
110 : bool Is2D(gfxMatrix* aMatrix) const;
111 : bool Is2D() const;
112 :
113 : /**
114 : * Returns true if the matrix can be reduced to a 2D affine transformation
115 : * (i.e. as obtained by From2D). If it is, optionally returns the 2D
116 : * matrix in aMatrix. This should only be used on matrices required for
117 : * rendering, not for intermediate calculations. It is assumed that the 2D
118 : * matrix will only be used for transforming objects on to the z=0 plane,
119 : * therefore any z-component perspective is ignored. This means that if
120 : * aMatrix is applied to objects with z != 0, the results may be incorrect.
121 : *
122 : * Since drawing is to a 2d plane, any 3d transform without perspective
123 : * can be reduced by dropping the z row and column.
124 : */
125 : bool CanDraw2D(gfxMatrix* aMatrix = nsnull) const;
126 :
127 : /**
128 : * Converts the matrix to one that doesn't modify the z coordinate of points,
129 : * but leaves the rest of the transformation unchanged.
130 : */
131 : gfx3DMatrix& ProjectTo2D();
132 :
133 : /**
134 : * Returns true if the matrix is the identity matrix. The most important
135 : * property we require is that gfx3DMatrix().IsIdentity() returns true.
136 : */
137 : bool IsIdentity() const;
138 :
139 : /**
140 : * Pre-multiplication transformation functions:
141 : *
142 : * These functions construct a temporary matrix containing
143 : * a single transformation and pre-multiply it onto the current
144 : * matrix.
145 : */
146 :
147 : /**
148 : * Add a translation by aPoint to the matrix.
149 : *
150 : * This creates this temporary matrix:
151 : * | 1 0 0 0 |
152 : * | 0 1 0 0 |
153 : * | 0 0 1 0 |
154 : * | aPoint.x aPoint.y aPoint.z 1 |
155 : */
156 : void Translate(const gfxPoint3D& aPoint);
157 :
158 : /**
159 : * Skew the matrix.
160 : *
161 : * This creates this temporary matrix:
162 : * | 1 tan(aYSkew) 0 0 |
163 : * | tan(aXSkew) 1 0 0 |
164 : * | 0 0 1 0 |
165 : * | 0 0 0 1 |
166 : */
167 : void SkewXY(double aXSkew, double aYSkew);
168 :
169 : void SkewXY(double aSkew);
170 : void SkewXZ(double aSkew);
171 : void SkewYZ(double aSkew);
172 :
173 : /**
174 : * Scale the matrix
175 : *
176 : * This creates this temporary matrix:
177 : * | aX 0 0 0 |
178 : * | 0 aY 0 0 |
179 : * | 0 0 aZ 0 |
180 : * | 0 0 0 1 |
181 : */
182 : void Scale(float aX, float aY, float aZ);
183 :
184 : /**
185 : * Rotate around the X axis..
186 : *
187 : * This creates this temporary matrix:
188 : * | 1 0 0 0 |
189 : * | 0 cos(aTheta) sin(aTheta) 0 |
190 : * | 0 -sin(aTheta) cos(aTheta) 0 |
191 : * | 0 0 0 1 |
192 : */
193 : void RotateX(double aTheta);
194 :
195 : /**
196 : * Rotate around the Y axis..
197 : *
198 : * This creates this temporary matrix:
199 : * | cos(aTheta) 0 -sin(aTheta) 0 |
200 : * | 0 1 0 0 |
201 : * | sin(aTheta) 0 cos(aTheta) 0 |
202 : * | 0 0 0 1 |
203 : */
204 : void RotateY(double aTheta);
205 :
206 : /**
207 : * Rotate around the Z axis..
208 : *
209 : * This creates this temporary matrix:
210 : * | cos(aTheta) sin(aTheta) 0 0 |
211 : * | -sin(aTheta) cos(aTheta) 0 0 |
212 : * | 0 0 1 0 |
213 : * | 0 0 0 1 |
214 : */
215 : void RotateZ(double aTheta);
216 :
217 : /**
218 : * Apply perspective to the matrix.
219 : *
220 : * This creates this temporary matrix:
221 : * | 1 0 0 0 |
222 : * | 0 1 0 0 |
223 : * | 0 0 1 -1/aDepth |
224 : * | 0 0 0 1 |
225 : */
226 : void Perspective(float aDepth);
227 :
228 : /**
229 : * Pre multiply an existing matrix onto the current
230 : * matrix
231 : */
232 : void PreMultiply(const gfx3DMatrix& aOther);
233 : void PreMultiply(const gfxMatrix& aOther);
234 :
235 : /**
236 : * Post-multiplication transformation functions:
237 : *
238 : * These functions construct a temporary matrix containing
239 : * a single transformation and post-multiply it onto the current
240 : * matrix.
241 : */
242 :
243 : /**
244 : * Add a translation by aPoint after the matrix.
245 : * This is functionally equivalent to:
246 : * matrix * gfx3DMatrix::Translation(aPoint)
247 : */
248 : void TranslatePost(const gfxPoint3D& aPoint);
249 :
250 : /**
251 : * Transforms a point according to this matrix.
252 : */
253 : gfxPoint Transform(const gfxPoint& point) const;
254 :
255 : /**
256 : * Transforms a rectangle according to this matrix
257 : */
258 : gfxRect TransformBounds(const gfxRect& rect) const;
259 :
260 :
261 : gfxQuad TransformRect(const gfxRect& aRect) const;
262 :
263 : /**
264 : * Transforms a 3D vector according to this matrix.
265 : */
266 : gfxPoint3D Transform3D(const gfxPoint3D& point) const;
267 : gfxPointH3D Transform4D(const gfxPointH3D& aPoint) const;
268 : gfxPointH3D TransposeTransform4D(const gfxPointH3D& aPoint) const;
269 :
270 : gfxPoint ProjectPoint(const gfxPoint& aPoint) const;
271 : gfxRect ProjectRectBounds(const gfxRect& aRect) const;
272 :
273 :
274 : /**
275 : * Inverts this matrix, if possible. Otherwise, the matrix is left
276 : * unchanged.
277 : */
278 : gfx3DMatrix Inverse() const;
279 :
280 0 : gfx3DMatrix& Invert()
281 : {
282 0 : *this = Inverse();
283 0 : return *this;
284 : }
285 :
286 : gfx3DMatrix& Normalize();
287 :
288 0 : gfxPointH3D TransposedVector(int aIndex) const
289 : {
290 0 : NS_ABORT_IF_FALSE(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
291 0 : return gfxPointH3D(*((&_11)+aIndex), *((&_21)+aIndex), *((&_31)+aIndex), *((&_41)+aIndex));
292 : }
293 :
294 0 : void SetTransposedVector(int aIndex, gfxPointH3D &aVector)
295 : {
296 0 : NS_ABORT_IF_FALSE(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
297 0 : *((&_11)+aIndex) = aVector.x;
298 0 : *((&_21)+aIndex) = aVector.y;
299 0 : *((&_31)+aIndex) = aVector.z;
300 0 : *((&_41)+aIndex) = aVector.w;
301 0 : }
302 :
303 : gfx3DMatrix& Transpose();
304 : gfx3DMatrix Transposed() const;
305 :
306 : /**
307 : * Returns a unit vector that is perpendicular to the plane formed
308 : * by transform the screen plane (z=0) by this matrix.
309 : */
310 : gfxPoint3D GetNormalVector() const;
311 :
312 : /**
313 : * Returns true if a plane transformed by this matrix will
314 : * have it's back face visible.
315 : */
316 : bool IsBackfaceVisible() const;
317 :
318 : /**
319 : * Check if matrix is singular (no inverse exists).
320 : */
321 : bool IsSingular() const;
322 :
323 : /**
324 : * Create a translation matrix.
325 : *
326 : * \param aX Translation on X-axis.
327 : * \param aY Translation on Y-axis.
328 : * \param aZ Translation on Z-axis.
329 : */
330 : static gfx3DMatrix Translation(float aX, float aY, float aZ);
331 : static gfx3DMatrix Translation(const gfxPoint3D& aPoint);
332 :
333 : /**
334 : * Create a scale matrix. Scales uniformly along all axes.
335 : *
336 : * \param aScale Scale factor
337 : */
338 : static gfx3DMatrix ScalingMatrix(float aFactor);
339 :
340 : /**
341 : * Create a scale matrix.
342 : */
343 : static gfx3DMatrix ScalingMatrix(float aX, float aY, float aZ);
344 :
345 : gfxFloat Determinant() const;
346 :
347 : private:
348 :
349 : gfxFloat Determinant3x3() const;
350 : gfx3DMatrix Inverse3x3() const;
351 :
352 : gfx3DMatrix Multiply2D(const gfx3DMatrix &aMatrix) const;
353 :
354 : public:
355 :
356 : /** Matrix elements */
357 : float _11, _12, _13, _14;
358 : float _21, _22, _23, _24;
359 : float _31, _32, _33, _34;
360 : float _41, _42, _43, _44;
361 : };
362 :
363 : #endif /* GFX_3DMATRIX_H */
|