gfx/thebes/gfx3DMatrix.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/thebes/gfx3DMatrix.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,364 @@
     1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef GFX_3DMATRIX_H
    1.10 +#define GFX_3DMATRIX_H
    1.11 +
    1.12 +#include <gfxTypes.h>
    1.13 +#include <gfxPoint3D.h>
    1.14 +#include <gfxPointH3D.h>
    1.15 +#include <gfxQuad.h>
    1.16 +
    1.17 +struct gfxMatrix;
    1.18 +
    1.19 +/**
    1.20 + * This class represents a 3D transformation. The matrix is laid
    1.21 + * out as follows:
    1.22 + *
    1.23 + * _11 _12 _13 _14
    1.24 + * _21 _22 _23 _24
    1.25 + * _31 _32 _33 _34
    1.26 + * _41 _42 _43 _44
    1.27 + *
    1.28 + * This matrix is treated as row-major. Assuming we consider our vectors row
    1.29 + * vectors, this matrix type will be identical in memory to the OpenGL and D3D
    1.30 + * matrices. OpenGL matrices are column-major, however OpenGL also treats
    1.31 + * vectors as column vectors, the double transposition makes everything work
    1.32 + * out nicely.
    1.33 + */
    1.34 +class gfx3DMatrix
    1.35 +{
    1.36 +public:
    1.37 +  /**
    1.38 +   * Create matrix.
    1.39 +   */
    1.40 +  gfx3DMatrix(void);
    1.41 +
    1.42 +  /**
    1.43 +   * Matrix multiplication.
    1.44 +   */
    1.45 +  gfx3DMatrix operator*(const gfx3DMatrix &aMatrix) const;
    1.46 +  gfx3DMatrix& operator*=(const gfx3DMatrix &aMatrix);
    1.47 +
    1.48 +  gfxPointH3D& operator[](int aIndex)
    1.49 +  {
    1.50 +      NS_ABORT_IF_FALSE(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
    1.51 +      return *reinterpret_cast<gfxPointH3D*>((&_11)+4*aIndex);
    1.52 +  }
    1.53 +  const gfxPointH3D& operator[](int aIndex) const
    1.54 +  {
    1.55 +      NS_ABORT_IF_FALSE(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
    1.56 +      return *reinterpret_cast<const gfxPointH3D*>((&_11)+4*aIndex);
    1.57 +  }
    1.58 +
    1.59 +  /**
    1.60 +   * Return true if this matrix and |aMatrix| are the same matrix.
    1.61 +   */
    1.62 +  bool operator==(const gfx3DMatrix& aMatrix) const;
    1.63 +  bool operator!=(const gfx3DMatrix& aMatrix) const;
    1.64 +
    1.65 +  bool FuzzyEqual(const gfx3DMatrix& aMatrix) const;
    1.66 +  
    1.67 +  /**
    1.68 +   * Divide all values in the matrix by a scalar value
    1.69 +   */
    1.70 +  gfx3DMatrix& operator/=(gfxFloat scalar);
    1.71 +
    1.72 +  /**
    1.73 +   * Create a 3D matrix from a gfxMatrix 2D affine transformation.
    1.74 +   *
    1.75 +   * \param aMatrix gfxMatrix 2D affine transformation.
    1.76 +   */
    1.77 +  static gfx3DMatrix From2D(const gfxMatrix &aMatrix);
    1.78 +
    1.79 +  /**
    1.80 +   * Returns true if the matrix is isomorphic to a 2D affine transformation
    1.81 +   * (i.e. as obtained by From2D). If it is, optionally returns the 2D
    1.82 +   * matrix in aMatrix.
    1.83 +   */
    1.84 +  bool Is2D(gfxMatrix* aMatrix) const;
    1.85 +  bool Is2D() const;
    1.86 +
    1.87 +  /**
    1.88 +   * Returns true if the matrix can be reduced to a 2D affine transformation
    1.89 +   * (i.e. as obtained by From2D). If it is, optionally returns the 2D
    1.90 +   * matrix in aMatrix. This should only be used on matrices required for
    1.91 +   * rendering, not for intermediate calculations. It is assumed that the 2D
    1.92 +   * matrix will only be used for transforming objects on to the z=0 plane,
    1.93 +   * therefore any z-component perspective is ignored. This means that if
    1.94 +   * aMatrix is applied to objects with z != 0, the results may be incorrect.
    1.95 +   *
    1.96 +   * Since drawing is to a 2d plane, any 3d transform without perspective
    1.97 +   * can be reduced by dropping the z row and column.
    1.98 +   */
    1.99 +  bool CanDraw2D(gfxMatrix* aMatrix = nullptr) const;
   1.100 +
   1.101 +  /**
   1.102 +   * Converts the matrix to one that doesn't modify the z coordinate of points,
   1.103 +   * but leaves the rest of the transformation unchanged.
   1.104 +   */
   1.105 +  gfx3DMatrix& ProjectTo2D();
   1.106 +
   1.107 +  /**
   1.108 +   * Returns true if the matrix is the identity matrix. The most important
   1.109 +   * property we require is that gfx3DMatrix().IsIdentity() returns true.
   1.110 +   */
   1.111 +  bool IsIdentity() const;
   1.112 +
   1.113 +  /**
   1.114 +   * Pre-multiplication transformation functions:
   1.115 +   *
   1.116 +   * These functions construct a temporary matrix containing
   1.117 +   * a single transformation and pre-multiply it onto the current
   1.118 +   * matrix.
   1.119 +   */
   1.120 +
   1.121 +  /**
   1.122 +   * Add a translation by aPoint to the matrix.
   1.123 +   *
   1.124 +   * This creates this temporary matrix:
   1.125 +   * |  1        0        0         0 |
   1.126 +   * |  0        1        0         0 |
   1.127 +   * |  0        0        1         0 |
   1.128 +   * |  aPoint.x aPoint.y aPoint.z  1 |
   1.129 +   */
   1.130 +  void Translate(const gfxPoint3D& aPoint);
   1.131 +
   1.132 +  /** 
   1.133 +   * Skew the matrix.
   1.134 +   *
   1.135 +   * This creates this temporary matrix:
   1.136 +   * | 1           tan(aYSkew) 0 0 |
   1.137 +   * | tan(aXSkew) 1           0 0 |
   1.138 +   * | 0           0           1 0 |
   1.139 +   * | 0           0           0 1 |
   1.140 +   */
   1.141 +  void SkewXY(double aXSkew, double aYSkew);
   1.142 +  
   1.143 +  void SkewXY(double aSkew);
   1.144 +  void SkewXZ(double aSkew);
   1.145 +  void SkewYZ(double aSkew);
   1.146 +
   1.147 +  /**
   1.148 +   * Scale the matrix
   1.149 +   *
   1.150 +   * This creates this temporary matrix:
   1.151 +   * | aX 0  0  0 |
   1.152 +   * | 0  aY 0  0 |
   1.153 +   * | 0  0  aZ 0 |
   1.154 +   * | 0  0  0  1 |
   1.155 +   */
   1.156 +  void Scale(float aX, float aY, float aZ);
   1.157 +
   1.158 +  /**
   1.159 +   * Return the currently set scaling factors.
   1.160 +   */
   1.161 +  float GetXScale() const { return _11; }
   1.162 +  float GetYScale() const { return _22; }
   1.163 +  float GetZScale() const { return _33; }
   1.164 +
   1.165 +  /**
   1.166 +   * Rotate around the X axis..
   1.167 +   *
   1.168 +   * This creates this temporary matrix:
   1.169 +   * | 1 0            0           0 |
   1.170 +   * | 0 cos(aTheta)  sin(aTheta) 0 |
   1.171 +   * | 0 -sin(aTheta) cos(aTheta) 0 |
   1.172 +   * | 0 0            0           1 |
   1.173 +   */
   1.174 +  void RotateX(double aTheta);
   1.175 +  
   1.176 +  /**
   1.177 +   * Rotate around the Y axis..
   1.178 +   *
   1.179 +   * This creates this temporary matrix:
   1.180 +   * | cos(aTheta) 0 -sin(aTheta) 0 |
   1.181 +   * | 0           1 0            0 |
   1.182 +   * | sin(aTheta) 0 cos(aTheta)  0 |
   1.183 +   * | 0           0 0            1 |
   1.184 +   */
   1.185 +  void RotateY(double aTheta);
   1.186 +  
   1.187 +  /**
   1.188 +   * Rotate around the Z axis..
   1.189 +   *
   1.190 +   * This creates this temporary matrix:
   1.191 +   * | cos(aTheta)  sin(aTheta)  0 0 |
   1.192 +   * | -sin(aTheta) cos(aTheta)  0 0 |
   1.193 +   * | 0            0            1 0 |
   1.194 +   * | 0            0            0 1 |
   1.195 +   */
   1.196 +  void RotateZ(double aTheta);
   1.197 +
   1.198 +  /**
   1.199 +   * Apply perspective to the matrix.
   1.200 +   *
   1.201 +   * This creates this temporary matrix:
   1.202 +   * | 1 0 0 0         |
   1.203 +   * | 0 1 0 0         |
   1.204 +   * | 0 0 1 -1/aDepth |
   1.205 +   * | 0 0 0 1         |
   1.206 +   */
   1.207 +  void Perspective(float aDepth);
   1.208 +
   1.209 +  /**
   1.210 +   * Pre multiply an existing matrix onto the current
   1.211 +   * matrix
   1.212 +   */
   1.213 +  void PreMultiply(const gfx3DMatrix& aOther);
   1.214 +  void PreMultiply(const gfxMatrix& aOther);
   1.215 +
   1.216 +  /**
   1.217 +   * Post-multiplication transformation functions:
   1.218 +   *
   1.219 +   * These functions construct a temporary matrix containing
   1.220 +   * a single transformation and post-multiply it onto the current
   1.221 +   * matrix.
   1.222 +   */
   1.223 +
   1.224 +  /**
   1.225 +   * Add a translation by aPoint after the matrix.
   1.226 +   * This is functionally equivalent to:
   1.227 +   * matrix * gfx3DMatrix::Translation(aPoint)
   1.228 +   */
   1.229 +  void TranslatePost(const gfxPoint3D& aPoint);
   1.230 +
   1.231 +  void ScalePost(float aX, float aY, float aZ);
   1.232 +
   1.233 +  /**
   1.234 +   * Transforms a point according to this matrix.
   1.235 +   */
   1.236 +  gfxPoint Transform(const gfxPoint& point) const;
   1.237 +
   1.238 +  /**
   1.239 +   * Transforms a rectangle according to this matrix
   1.240 +   */
   1.241 +  gfxRect TransformBounds(const gfxRect& rect) const;
   1.242 +
   1.243 +
   1.244 +  gfxQuad TransformRect(const gfxRect& aRect) const;
   1.245 +
   1.246 +  /** 
   1.247 +   * Transforms a 3D vector according to this matrix.
   1.248 +   */
   1.249 +  gfxPoint3D Transform3D(const gfxPoint3D& point) const;
   1.250 +  gfxPointH3D Transform4D(const gfxPointH3D& aPoint) const;
   1.251 +  gfxPointH3D TransposeTransform4D(const gfxPointH3D& aPoint) const;
   1.252 +
   1.253 +  gfxPoint ProjectPoint(const gfxPoint& aPoint) const;
   1.254 +  gfxRect ProjectRectBounds(const gfxRect& aRect) const;
   1.255 +
   1.256 +  /**
   1.257 +   * Transforms a point by the inverse of this matrix. In the case of perspective transforms, some screen
   1.258 +   * points have no equivalent in the untransformed plane (if they exist past the vanishing point). To
   1.259 +   * avoid this, we need to specify the bounds of the untransformed plane to restrict the search area.
   1.260 +   *
   1.261 +   * @param aPoint Point to untransform.
   1.262 +   * @param aChildBounds Bounds of the untransformed plane.
   1.263 +   * @param aOut Untransformed point.
   1.264 +   * @return Returns true if a point was found within a ChildBounds, false otherwise.
   1.265 +   */
   1.266 +  bool UntransformPoint(const gfxPoint& aPoint, const gfxRect& aChildBounds, gfxPoint* aOut) const;
   1.267 +
   1.268 +
   1.269 +  /**
   1.270 +   * Same as UntransformPoint, but untransforms a rect and returns the bounding rect of the result.
   1.271 +   * Returns an empty rect if the result doesn't intersect aChildBounds.
   1.272 +   */
   1.273 +  gfxRect UntransformBounds(const gfxRect& aRect, const gfxRect& aChildBounds) const;
   1.274 +
   1.275 +
   1.276 +  /**
   1.277 +   * Inverts this matrix, if possible. Otherwise, the matrix is left
   1.278 +   * unchanged.
   1.279 +   */
   1.280 +  gfx3DMatrix Inverse() const;
   1.281 +
   1.282 +  gfx3DMatrix& Invert()
   1.283 +  {
   1.284 +      *this = Inverse();
   1.285 +      return *this;
   1.286 +  }
   1.287 +
   1.288 +  gfx3DMatrix& Normalize();
   1.289 +
   1.290 +  gfxPointH3D TransposedVector(int aIndex) const
   1.291 +  {
   1.292 +      NS_ABORT_IF_FALSE(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
   1.293 +      return gfxPointH3D(*((&_11)+aIndex), *((&_21)+aIndex), *((&_31)+aIndex), *((&_41)+aIndex));
   1.294 +  }
   1.295 +
   1.296 +  void SetTransposedVector(int aIndex, gfxPointH3D &aVector)
   1.297 +  {
   1.298 +      NS_ABORT_IF_FALSE(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
   1.299 +      *((&_11)+aIndex) = aVector.x;
   1.300 +      *((&_21)+aIndex) = aVector.y;
   1.301 +      *((&_31)+aIndex) = aVector.z;
   1.302 +      *((&_41)+aIndex) = aVector.w;
   1.303 +  }
   1.304 +
   1.305 +  gfx3DMatrix& Transpose();
   1.306 +  gfx3DMatrix Transposed() const;
   1.307 +
   1.308 +  /**
   1.309 +   * Returns a unit vector that is perpendicular to the plane formed
   1.310 +   * by transform the screen plane (z=0) by this matrix.
   1.311 +   */
   1.312 +  gfxPoint3D GetNormalVector() const;
   1.313 +
   1.314 +  /**
   1.315 +   * Returns true if a plane transformed by this matrix will
   1.316 +   * have it's back face visible.
   1.317 +   */
   1.318 +  bool IsBackfaceVisible() const;
   1.319 +
   1.320 +  /**
   1.321 +   * Check if matrix is singular (no inverse exists).
   1.322 +   */
   1.323 +  bool IsSingular() const;
   1.324 +
   1.325 +  /**
   1.326 +   * Create a translation matrix.
   1.327 +   *
   1.328 +   * \param aX Translation on X-axis.
   1.329 +   * \param aY Translation on Y-axis.
   1.330 +   * \param aZ Translation on Z-axis.
   1.331 +   */
   1.332 +  static gfx3DMatrix Translation(float aX, float aY, float aZ);
   1.333 +  static gfx3DMatrix Translation(const gfxPoint3D& aPoint);
   1.334 +
   1.335 +  /**
   1.336 +   * Create a scale matrix. Scales uniformly along all axes.
   1.337 +   *
   1.338 +   * \param aScale Scale factor
   1.339 +   */
   1.340 +  static gfx3DMatrix ScalingMatrix(float aFactor);
   1.341 +
   1.342 +  /**
   1.343 +   * Create a scale matrix.
   1.344 +   */
   1.345 +  static gfx3DMatrix ScalingMatrix(float aX, float aY, float aZ);
   1.346 +
   1.347 +  gfxFloat Determinant() const;
   1.348 +
   1.349 +  void NudgeToIntegers(void);
   1.350 +
   1.351 +private:
   1.352 +
   1.353 +  gfxFloat Determinant3x3() const;
   1.354 +  gfx3DMatrix Inverse3x3() const;
   1.355 +
   1.356 +  gfx3DMatrix Multiply2D(const gfx3DMatrix &aMatrix) const;
   1.357 +
   1.358 +public:
   1.359 +
   1.360 +  /** Matrix elements */
   1.361 +  float _11, _12, _13, _14;
   1.362 +  float _21, _22, _23, _24;
   1.363 +  float _31, _32, _33, _34;
   1.364 +  float _41, _42, _43, _44;
   1.365 +};
   1.366 +
   1.367 +#endif /* GFX_3DMATRIX_H */

mercurial