18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. 30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2009 Torch Mobile, Inc. 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "TransformationMatrix.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 30ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "AffineTransform.h" 318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "FloatPoint3D.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FloatRect.h" 33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "FloatQuad.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "IntRect.h" 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include <wtf/Assertions.h> 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/MathExtras.h> 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Supporting Math Functions 438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// This is a set of function from various places (attributed inline) to do things like 458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// inversion and decomposition of a 4x4 matrix. They are used throughout the code 468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Adapted from Matrix Inversion by Richard Carling, Graphics Gems <http://tog.acm.org/GraphicsGems/index.html>. 508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// EULA: The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code 528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// as your own and resell it. Using the code is permitted in any program, product, or library, non-commercial 538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// or commercial. Giving credit is not required, though is a nice gesture. The code comes as-is, and if there 548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// are any flaws or problems with any Gems code, nobody involved with Gems - authors, editors, publishers, or 558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes 568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// with no guarantee. 578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// A clarification about the storage of matrix elements 5921939df44de1705786c545cd1bf519d47250322dBen Murdoch// 602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// This class uses a 2 dimensional array internally to store the elements of the matrix. The first index into 612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// the array refers to the column that the element lies in; the second index refers to the row. 6221939df44de1705786c545cd1bf519d47250322dBen Murdoch// 632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// In other words, this is the layout of the matrix: 642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// 652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// | m_matrix[0][0] m_matrix[1][0] m_matrix[2][0] m_matrix[3][0] | 662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// | m_matrix[0][1] m_matrix[1][1] m_matrix[2][1] m_matrix[3][1] | 672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// | m_matrix[0][2] m_matrix[1][2] m_matrix[2][2] m_matrix[3][2] | 682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// | m_matrix[0][3] m_matrix[1][3] m_matrix[2][3] m_matrix[3][3] | 6921939df44de1705786c545cd1bf519d47250322dBen Murdoch 708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qiantypedef double Vector4[4]; 718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qiantypedef double Vector3[3]; 728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianconst double SMALL_NUMBER = 1.e-8; 748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// inverse(original_matrix, inverse_matrix) 768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// calculate the inverse of a 4x4 matrix 788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// -1 808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// A = ___1__ adjoint A 818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// det A 828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// double = determinant2x2(double a, double b, double c, double d) 848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// calculate the determinant of a 2x2 matrix. 868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double determinant2x2(double a, double b, double c, double d) 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return a * d - b * c; 908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// double = determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3) 938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Calculate the determinant of a 3x3 matrix 958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// in the form 968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// | a1, b1, c1 | 988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// | a2, b2, c2 | 998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// | a3, b3, c3 | 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double determinant3x3(double a1, double a2, double a3, double b1, double b2, double b3, double c1, double c2, double c3) 1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return a1 * determinant2x2(b2, b3, c2, c3) 1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian - b1 * determinant2x2(a2, a3, c2, c3) 1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + c1 * determinant2x2(a2, a3, b2, b3); 1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// double = determinant4x4(matrix) 1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// calculate the determinant of a 4x4 matrix. 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double determinant4x4(const TransformationMatrix::Matrix4& m) 1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Assign to individual variable names to aid selecting 1158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // correct elements 1168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double a1 = m[0][0]; 1188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double b1 = m[0][1]; 1198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double c1 = m[0][2]; 1208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double d1 = m[0][3]; 1218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double a2 = m[1][0]; 1238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double b2 = m[1][1]; 1248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double c2 = m[1][2]; 1258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double d2 = m[1][3]; 1268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double a3 = m[2][0]; 1288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double b3 = m[2][1]; 1298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double c3 = m[2][2]; 1308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double d3 = m[2][3]; 1318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double a4 = m[3][0]; 1338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double b4 = m[3][1]; 1348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double c4 = m[3][2]; 1358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double d4 = m[3][3]; 1368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return a1 * determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4) 1388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian - b1 * determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4) 1398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + c1 * determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4) 1408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian - d1 * determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4); 1418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 1428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// adjoint( original_matrix, inverse_matrix ) 1448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 1458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// calculate the adjoint of a 4x4 matrix 1468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 1478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Let a denote the minor determinant of matrix A obtained by 1488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// ij 1498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 1508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// deleting the ith row and jth column from A. 1518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// i+j 1538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Let b = (-1) a 1548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// ij ji 1558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 1568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// The matrix B = (b ) is the adjoint of A 1578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// ij 1588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void adjoint(const TransformationMatrix::Matrix4& matrix, TransformationMatrix::Matrix4& result) 1608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 1618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Assign to individual variable names to aid 1628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // selecting correct values 1638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double a1 = matrix[0][0]; 1648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double b1 = matrix[0][1]; 1658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double c1 = matrix[0][2]; 1668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double d1 = matrix[0][3]; 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double a2 = matrix[1][0]; 1698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double b2 = matrix[1][1]; 1708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double c2 = matrix[1][2]; 1718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double d2 = matrix[1][3]; 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double a3 = matrix[2][0]; 1748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double b3 = matrix[2][1]; 1758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double c3 = matrix[2][2]; 1768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double d3 = matrix[2][3]; 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double a4 = matrix[3][0]; 1798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double b4 = matrix[3][1]; 1808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double c4 = matrix[3][2]; 1818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double d4 = matrix[3][3]; 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Row column labeling reversed since we transpose rows & columns 1848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[0][0] = determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4); 1858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[1][0] = - determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4); 1868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[2][0] = determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4); 1878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[3][0] = - determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4); 1888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[0][1] = - determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4); 1908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[1][1] = determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4); 1918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[2][1] = - determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4); 1928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[3][1] = determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4); 1938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[0][2] = determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4); 1958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[1][2] = - determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4); 1968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[2][2] = determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4); 1978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[3][2] = - determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4); 1988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[0][3] = - determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3); 2008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[1][3] = determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3); 2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[2][3] = - determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3); 2028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[3][3] = determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3); 2038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 2048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Returns false if the matrix is not invertible 2068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic bool inverse(const TransformationMatrix::Matrix4& matrix, TransformationMatrix::Matrix4& result) 2078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 2088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Calculate the adjoint matrix 2098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian adjoint(matrix, result); 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Calculate the 4x4 determinant 2128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // If the determinant is zero, 2138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // then the inverse matrix is not unique. 2148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double det = determinant4x4(matrix); 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (fabs(det) < SMALL_NUMBER) 2178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return false; 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Scale the adjoint matrix to get the inverse 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (int i = 0; i < 4; i++) 2228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (int j = 0; j < 4; j++) 2238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[i][j] = result[i][j] / det; 2248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return true; 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// End of code adapted from Matrix Inversion by Richard Carling 2298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Perform a decomposition on the passed matrix, return false if unsuccessful 2318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// From Graphics Gems: unmatrix.c 2328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Transpose rotation portion of matrix a, return b 2348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void transposeMatrix4(const TransformationMatrix::Matrix4& a, TransformationMatrix::Matrix4& b) 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (int i = 0; i < 4; i++) 2378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (int j = 0; j < 4; j++) 2388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian b[i][j] = a[j][i]; 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Multiply a homogeneous point by a matrix and return the transformed point 2428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void v4MulPointByMatrix(const Vector4 p, const TransformationMatrix::Matrix4& m, Vector4 result) 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[0] = (p[0] * m[0][0]) + (p[1] * m[1][0]) + 2458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian (p[2] * m[2][0]) + (p[3] * m[3][0]); 2468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[1] = (p[0] * m[0][1]) + (p[1] * m[1][1]) + 2478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian (p[2] * m[2][1]) + (p[3] * m[3][1]); 2488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[2] = (p[0] * m[0][2]) + (p[1] * m[1][2]) + 2498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian (p[2] * m[2][2]) + (p[3] * m[3][2]); 2508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[3] = (p[0] * m[0][3]) + (p[1] * m[1][3]) + 2518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian (p[2] * m[2][3]) + (p[3] * m[3][3]); 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double v3Length(Vector3 a) 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return sqrt((a[0] * a[0]) + (a[1] * a[1]) + (a[2] * a[2])); 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void v3Scale(Vector3 v, double desiredLength) 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double len = v3Length(v); 2628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (len != 0) { 2638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double l = desiredLength / len; 2648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v[0] *= l; 2658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v[1] *= l; 2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v[2] *= l; 2678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double v3Dot(const Vector3 a, const Vector3 b) 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]); 2738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 2748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Make a linear combination of two vectors and return the result. 2768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// result = (a * ascl) + (b * bscl) 2778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void v3Combine(const Vector3 a, const Vector3 b, Vector3 result, double ascl, double bscl) 2788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 2798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[0] = (ascl * a[0]) + (bscl * b[0]); 2808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[1] = (ascl * a[1]) + (bscl * b[1]); 2818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[2] = (ascl * a[2]) + (bscl * b[2]); 2828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 2838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Return the cross product result = a cross b */ 2858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void v3Cross(const Vector3 a, const Vector3 b, Vector3 result) 2868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 2878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[0] = (a[1] * b[2]) - (a[2] * b[1]); 2888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[1] = (a[2] * b[0]) - (a[0] * b[2]); 2898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result[2] = (a[0] * b[1]) - (a[1] * b[0]); 2908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 2918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic bool decompose(const TransformationMatrix::Matrix4& mat, TransformationMatrix::DecomposedType& result) 2938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 2948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix::Matrix4 localMatrix; 2958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian memcpy(localMatrix, mat, sizeof(TransformationMatrix::Matrix4)); 2968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Normalize the matrix. 2988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (localMatrix[3][3] == 0) 2998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return false; 3008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int i, j; 3028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (i = 0; i < 4; i++) 3038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (j = 0; j < 4; j++) 3048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian localMatrix[i][j] /= localMatrix[3][3]; 3058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // perspectiveMatrix is used to solve for perspective, but it also provides 3078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // an easy way to test for singularity of the upper 3x3 component. 3088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix::Matrix4 perspectiveMatrix; 3098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian memcpy(perspectiveMatrix, localMatrix, sizeof(TransformationMatrix::Matrix4)); 3108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (i = 0; i < 3; i++) 3118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian perspectiveMatrix[i][3] = 0; 3128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian perspectiveMatrix[3][3] = 1; 3138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (determinant4x4(perspectiveMatrix) == 0) 3158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return false; 3168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // First, isolate perspective. This is the messiest. 3188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (localMatrix[0][3] != 0 || localMatrix[1][3] != 0 || localMatrix[2][3] != 0) { 3198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // rightHandSide is the right hand side of the equation. 3208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Vector4 rightHandSide; 3218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rightHandSide[0] = localMatrix[0][3]; 3228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rightHandSide[1] = localMatrix[1][3]; 3238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rightHandSide[2] = localMatrix[2][3]; 3248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rightHandSide[3] = localMatrix[3][3]; 3258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Solve the equation by inverting perspectiveMatrix and multiplying 3278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // rightHandSide by the inverse. (This is the easiest way, not 3288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // necessarily the best.) 3298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix::Matrix4 inversePerspectiveMatrix, transposedInversePerspectiveMatrix; 3308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian inverse(perspectiveMatrix, inversePerspectiveMatrix); 3318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian transposeMatrix4(inversePerspectiveMatrix, transposedInversePerspectiveMatrix); 3328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Vector4 perspectivePoint; 3348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v4MulPointByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspectivePoint); 3358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.perspectiveX = perspectivePoint[0]; 3378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.perspectiveY = perspectivePoint[1]; 3388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.perspectiveZ = perspectivePoint[2]; 3398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.perspectiveW = perspectivePoint[3]; 3408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Clear the perspective partition 3428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian localMatrix[0][3] = localMatrix[1][3] = localMatrix[2][3] = 0; 3438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian localMatrix[3][3] = 1; 3448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else { 3458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // No perspective. 3468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.perspectiveX = result.perspectiveY = result.perspectiveZ = 0; 3478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.perspectiveW = 1; 3488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 3498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Next take care of translation (easy). 3518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.translateX = localMatrix[3][0]; 3528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian localMatrix[3][0] = 0; 3538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.translateY = localMatrix[3][1]; 3548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian localMatrix[3][1] = 0; 3558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.translateZ = localMatrix[3][2]; 3568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian localMatrix[3][2] = 0; 3578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Vector4 type and functions need to be added to the common set. 3598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Vector3 row[3], pdum3; 3608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Now get scale and shear. 3628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (i = 0; i < 3; i++) { 3638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian row[i][0] = localMatrix[i][0]; 3648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian row[i][1] = localMatrix[i][1]; 3658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian row[i][2] = localMatrix[i][2]; 3668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 3678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Compute X scale factor and normalize first row. 3698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.scaleX = v3Length(row[0]); 3708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v3Scale(row[0], 1.0); 3718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Compute XY shear factor and make 2nd row orthogonal to 1st. 3738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.skewXY = v3Dot(row[0], row[1]); 3748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v3Combine(row[1], row[0], row[1], 1.0, -result.skewXY); 3758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Now, compute Y scale and normalize 2nd row. 3778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.scaleY = v3Length(row[1]); 3788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v3Scale(row[1], 1.0); 3798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.skewXY /= result.scaleY; 3808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Compute XZ and YZ shears, orthogonalize 3rd row. 3828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.skewXZ = v3Dot(row[0], row[2]); 3838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v3Combine(row[2], row[0], row[2], 1.0, -result.skewXZ); 3848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.skewYZ = v3Dot(row[1], row[2]); 3858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v3Combine(row[2], row[1], row[2], 1.0, -result.skewYZ); 3868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Next, get Z scale and normalize 3rd row. 3888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.scaleZ = v3Length(row[2]); 3898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v3Scale(row[2], 1.0); 3908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.skewXZ /= result.scaleZ; 3918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.skewYZ /= result.scaleZ; 3928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // At this point, the matrix (in rows[]) is orthonormal. 3948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Check for a coordinate system flip. If the determinant 3958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // is -1, then negate the matrix and the scaling factors. 3968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian v3Cross(row[1], row[2], pdum3); 3978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (v3Dot(row[0], pdum3) < 0) { 3988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (i = 0; i < 3; i++) { 3998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.scaleX *= -1; 4008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian row[i][0] *= -1; 4018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian row[i][1] *= -1; 4028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian row[i][2] *= -1; 4038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 4048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 4058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Now, get the rotations out, as described in the gem. 4078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // FIXME - Add the ability to return either quaternions (which are 4098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // easier to recompose with) or Euler angles (rx, ry, rz), which 4108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // are easier for authors to deal with. The latter will only be useful 4118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // when we fix https://bugs.webkit.org/show_bug.cgi?id=23799, so I 4128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // will leave the Euler angle code here for now. 4138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // ret.rotateY = asin(-row[0][2]); 4158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // if (cos(ret.rotateY) != 0) { 4168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // ret.rotateX = atan2(row[1][2], row[2][2]); 4178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // ret.rotateZ = atan2(row[0][1], row[0][0]); 4188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // } else { 4198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // ret.rotateX = atan2(-row[2][0], row[1][1]); 4208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // ret.rotateZ = 0; 4218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // } 4228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double s, t, x, y, z, w; 4248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian t = row[0][0] + row[1][1] + row[2][2] + 1.0; 4268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (t > 1e-4) { 4288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian s = 0.5 / sqrt(t); 4298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian w = 0.25 / s; 4308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian x = (row[2][1] - row[1][2]) * s; 4318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian y = (row[0][2] - row[2][0]) * s; 4328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian z = (row[1][0] - row[0][1]) * s; 4338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) { 4348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian s = sqrt (1.0 + row[0][0] - row[1][1] - row[2][2]) * 2.0; // S=4*qx 4358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian x = 0.25 * s; 4368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian y = (row[0][1] + row[1][0]) / s; 4378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian z = (row[0][2] + row[2][0]) / s; 4388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian w = (row[2][1] - row[1][2]) / s; 4398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else if (row[1][1] > row[2][2]) { 4408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian s = sqrt (1.0 + row[1][1] - row[0][0] - row[2][2]) * 2.0; // S=4*qy 4418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian x = (row[0][1] + row[1][0]) / s; 4428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian y = 0.25 * s; 4438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian z = (row[1][2] + row[2][1]) / s; 4448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian w = (row[0][2] - row[2][0]) / s; 4458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else { 4468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian s = sqrt(1.0 + row[2][2] - row[0][0] - row[1][1]) * 2.0; // S=4*qz 4478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian x = (row[0][2] + row[2][0]) / s; 4488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian y = (row[1][2] + row[2][1]) / s; 4498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian z = 0.25 * s; 4508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian w = (row[1][0] - row[0][1]) / s; 4518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 4528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.quaternionX = x; 4548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.quaternionY = y; 4558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.quaternionZ = z; 4568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.quaternionW = w; 4578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return true; 4598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 4608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Perform a spherical linear interpolation between the two 4628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// passed quaternions with 0 <= t <= 1 4638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void slerp(double qa[4], const double qb[4], double t) 4648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 4658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double ax, ay, az, aw; 4668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double bx, by, bz, bw; 4678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double cx, cy, cz, cw; 4688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double angle; 4698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double th, invth, scale, invscale; 4708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ax = qa[0]; ay = qa[1]; az = qa[2]; aw = qa[3]; 4728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bx = qb[0]; by = qb[1]; bz = qb[2]; bw = qb[3]; 4738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian angle = ax * bx + ay * by + az * bz + aw * bw; 4758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (angle < 0.0) { 4778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ax = -ax; ay = -ay; 4788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian az = -az; aw = -aw; 4798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian angle = -angle; 4808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 4818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (angle + 1.0 > .05) { 4838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (1.0 - angle >= .05) { 4848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian th = acos (angle); 4858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian invth = 1.0 / sin (th); 4868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian scale = sin (th * (1.0 - t)) * invth; 4878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian invscale = sin (th * t) * invth; 4888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else { 4898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian scale = 1.0 - t; 4908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian invscale = t; 4918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 4928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else { 4938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bx = -ay; 4948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian by = ax; 4958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bz = -aw; 4968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bw = az; 4978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian scale = sin(piDouble * (.5 - t)); 4988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian invscale = sin (piDouble * t); 4998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 5008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian cx = ax * scale + bx * invscale; 5028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian cy = ay * scale + by * invscale; 5038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian cz = az * scale + bz * invscale; 5048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian cw = aw * scale + bw * invscale; 5058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian qa[0] = cx; qa[1] = cy; qa[2] = cz; qa[3] = cw; 5078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 5088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// End of Supporting Math Functions 5108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::scale(double s) 5128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 5138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return scaleNonUniform(s, s); 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 516635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectTransformationMatrix& TransformationMatrix::rotateFromVector(double x, double y) 5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return rotate(rad2deg(atan2(y, x))); 5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 521635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectTransformationMatrix& TransformationMatrix::flipX() 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return scaleNonUniform(-1.0f, 1.0f); 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 526635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectTransformationMatrix& TransformationMatrix::flipY() 5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return scaleNonUniform(1.0f, -1.0f); 5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatPoint TransformationMatrix::projectPoint(const FloatPoint& p) const 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // This is basically raytracing. We have a point in the destination 5348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // plane with z=0, and we cast a ray parallel to the z-axis from that 5358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // point to find the z-position at which it intersects the z=0 plane 5368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // with the transform applied. Once we have that point we apply the 5378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // inverse transform to find the corresponding point in the source 5388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // space. 5398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // 5408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Given a plane with normal Pn, and a ray starting at point R0 and 5418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // with direction defined by the vector Rd, we can find the 5428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // intersection point as a distance d from R0 in units of Rd by: 5438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // 5448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // d = -dot (Pn', R0) / dot (Pn', Rd) 5458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double x = p.x(); 5478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double y = p.y(); 5488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double z = -(m13() * x + m23() * y + m43()) / m33(); 5498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double outX = x * m11() + y * m21() + z * m31() + m41(); 5518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double outY = x * m12() + y * m22() + z * m32() + m42(); 5528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double w = x * m14() + y * m24() + z * m34() + m44(); 5548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (w != 1 && w != 0) { 5558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian outX /= w; 5568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian outY /= w; 5578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 5588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return FloatPoint(static_cast<float>(outX), static_cast<float>(outY)); 5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatQuad TransformationMatrix::projectQuad(const FloatQuad& q) const 5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian FloatQuad projectedQuad; 5658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian projectedQuad.setP1(projectPoint(q.p1())); 5668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian projectedQuad.setP2(projectPoint(q.p2())); 5678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian projectedQuad.setP3(projectPoint(q.p3())); 5688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian projectedQuad.setP4(projectPoint(q.p4())); 5698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return projectedQuad; 5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatPoint TransformationMatrix::mapPoint(const FloatPoint& p) const 5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (isIdentityOrTranslation()) 5755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return FloatPoint(p.x() + static_cast<float>(m_matrix[3][0]), p.y() + static_cast<float>(m_matrix[3][1])); 5765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 5778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double x, y; 5788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian multVecMatrix(p.x(), p.y(), x, y); 5798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return FloatPoint(static_cast<float>(x), static_cast<float>(y)); 5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatPoint3D TransformationMatrix::mapPoint(const FloatPoint3D& p) const 5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (isIdentityOrTranslation()) 5855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return FloatPoint3D(p.x() + static_cast<float>(m_matrix[3][0]), 5865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian p.y() + static_cast<float>(m_matrix[3][1]), 5875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian p.z() + static_cast<float>(m_matrix[3][2])); 5885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 5898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double x, y, z; 5908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian multVecMatrix(p.x(), p.y(), p.z(), x, y, z); 5918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return FloatPoint3D(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)); 5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianIntRect TransformationMatrix::mapRect(const IntRect &rect) const 5958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 5968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return enclosingIntRect(mapRect(FloatRect(rect))); 5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatRect TransformationMatrix::mapRect(const FloatRect& r) const 6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (isIdentityOrTranslation()) { 6025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian FloatRect mappedRect(r); 6035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian mappedRect.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1])); 6045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return mappedRect; 6055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 6065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 6078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian FloatQuad resultQuad = mapQuad(FloatQuad(r)); 6088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return resultQuad.boundingBox(); 6098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatQuad TransformationMatrix::mapQuad(const FloatQuad& q) const 6128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 6135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (isIdentityOrTranslation()) { 6145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian FloatQuad mappedQuad(q); 6155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian mappedQuad.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1])); 6165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return mappedQuad; 6175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 6185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 6198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian FloatQuad result; 6208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.setP1(mapPoint(q.p1())); 6218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.setP2(mapPoint(q.p2())); 6228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.setP3(mapPoint(q.p3())); 6238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.setP4(mapPoint(q.p4())); 6248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return result; 6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::scaleNonUniform(double sx, double sy) 628635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 6298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix mat; 6308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][0] = sx; 6318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][1] = sy; 6328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 6332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(mat); 6348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 635635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 636635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 6378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::scale3d(double sx, double sy, double sz) 6388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 6398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix mat; 6408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][0] = sx; 6418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][1] = sy; 6428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][2] = sz; 6438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 6442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(mat); 6458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 6468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 6478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 6488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double z, double angle) 6498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 6508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // angles are in degrees. Switch to radians 6518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian angle = deg2rad(angle); 6528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 6538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian angle /= 2.0f; 6548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double sinA = sin(angle); 6558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double cosA = cos(angle); 6568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double sinA2 = sinA * sinA; 6578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 6588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // normalize 6598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double length = sqrt(x * x + y * y + z * z); 6608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (length == 0) { 6618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // bad vector, just use something reasonable 6628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian x = 0; 6638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian y = 0; 6648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian z = 1; 6658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else if (length != 1) { 6668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian x /= length; 6678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian y /= length; 6688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian z /= length; 6698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 6708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 6718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix mat; 6728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 6738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // optimize case where axis is along major axis 6748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (x == 1.0f && y == 0.0f && z == 0.0f) { 6758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][0] = 1.0f; 6768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][1] = 0.0f; 6778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][2] = 0.0f; 6788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][0] = 0.0f; 6798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2; 6808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][2] = 2.0f * sinA * cosA; 6818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][0] = 0.0f; 6828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][1] = -2.0f * sinA * cosA; 6838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2; 6848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; 6858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; 6868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][3] = 1.0f; 6878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else if (x == 0.0f && y == 1.0f && z == 0.0f) { 6888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2; 6898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][1] = 0.0f; 6908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][2] = -2.0f * sinA * cosA; 6918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][0] = 0.0f; 6928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][1] = 1.0f; 6938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][2] = 0.0f; 6948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][0] = 2.0f * sinA * cosA; 6958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][1] = 0.0f; 6968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2; 6978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; 6988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; 6998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][3] = 1.0f; 7008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else if (x == 0.0f && y == 0.0f && z == 1.0f) { 7018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2; 7028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][1] = 2.0f * sinA * cosA; 7038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][2] = 0.0f; 7048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][0] = -2.0f * sinA * cosA; 7058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2; 7068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][2] = 0.0f; 7078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][0] = 0.0f; 7088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][1] = 0.0f; 7098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][2] = 1.0f; 7108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; 7118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; 7128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][3] = 1.0f; 7138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else { 7148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double x2 = x*x; 7158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double y2 = y*y; 7168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double z2 = z*z; 7178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][0] = 1.0f - 2.0f * (y2 + z2) * sinA2; 7198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][1] = 2.0f * (x * y * sinA2 + z * sinA * cosA); 7208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][2] = 2.0f * (x * z * sinA2 - y * sinA * cosA); 7218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][0] = 2.0f * (y * x * sinA2 - z * sinA * cosA); 7228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][1] = 1.0f - 2.0f * (z2 + x2) * sinA2; 7238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][2] = 2.0f * (y * z * sinA2 + x * sinA * cosA); 7248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][0] = 2.0f * (z * x * sinA2 + y * sinA * cosA); 7258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][1] = 2.0f * (z * y * sinA2 - x * sinA * cosA); 7268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][2] = 1.0f - 2.0f * (x2 + y2) * sinA2; 7278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; 7288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; 7298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][3] = 1.0f; 7308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 7312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(mat); 7328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 7338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 7348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, double rz) 7368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 7378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // angles are in degrees. Switch to radians 7388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rx = deg2rad(rx); 7398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ry = deg2rad(ry); 7408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rz = deg2rad(rz); 7418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix mat; 7438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rz /= 2.0f; 7458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double sinA = sin(rz); 7468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double cosA = cos(rz); 7478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double sinA2 = sinA * sinA; 7488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2; 7508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][1] = 2.0f * sinA * cosA; 7518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][2] = 0.0f; 7528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][0] = -2.0f * sinA * cosA; 7538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2; 7548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][2] = 0.0f; 7558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][0] = 0.0f; 7568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][1] = 0.0f; 7578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][2] = 1.0f; 7588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; 7598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; 7608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][3] = 1.0f; 7618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix rmat(mat); 7638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ry /= 2.0f; 7658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian sinA = sin(ry); 7668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian cosA = cos(ry); 7678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian sinA2 = sinA * sinA; 7688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2; 7708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][1] = 0.0f; 7718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][2] = -2.0f * sinA * cosA; 7728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][0] = 0.0f; 7738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][1] = 1.0f; 7748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][2] = 0.0f; 7758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][0] = 2.0f * sinA * cosA; 7768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][1] = 0.0f; 7778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2; 7788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; 7798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; 7808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][3] = 1.0f; 7818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block rmat.multiply(mat); 7838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rx /= 2.0f; 7858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian sinA = sin(rx); 7868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian cosA = cos(rx); 7878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian sinA2 = sinA * sinA; 7888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][0] = 1.0f; 7908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][1] = 0.0f; 7918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][2] = 0.0f; 7928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][0] = 0.0f; 7938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2; 7948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][2] = 2.0f * sinA * cosA; 7958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][0] = 0.0f; 7968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][1] = -2.0f * sinA * cosA; 7978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2; 7988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; 7998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; 8008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[3][3] = 1.0f; 8018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block rmat.multiply(mat); 8038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(rmat); 8058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 8068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 8078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::translate(double tx, double ty) 8098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 810353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0]; 811353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1]; 812353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2]; 813353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3]; 8148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 8158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 8168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::translate3d(double tx, double ty, double tz) 8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 819353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0] + tz * m_matrix[2][0]; 820353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1] + tz * m_matrix[2][1]; 821353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2] + tz * m_matrix[2][2]; 822353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3] + tz * m_matrix[2][3]; 8238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 8248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::translateRight(double tx, double ty) 8278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 8288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (tx != 0) { 8298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[0][0] += m_matrix[0][3] * tx; 8308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[1][0] += m_matrix[1][3] * tx; 8318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[2][0] += m_matrix[2][3] * tx; 8328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[3][0] += m_matrix[3][3] * tx; 8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (ty != 0) { 8368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[0][1] += m_matrix[0][3] * ty; 8378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[1][1] += m_matrix[1][3] * ty; 8388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[2][1] += m_matrix[2][3] * ty; 8398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[3][1] += m_matrix[3][3] * ty; 8408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 8438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 8448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::translateRight3d(double tx, double ty, double tz) 8468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 8478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian translateRight(tx, ty); 8488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (tz != 0) { 8498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[0][2] += m_matrix[0][3] * tz; 8508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[1][2] += m_matrix[1][3] * tz; 8518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[2][2] += m_matrix[2][3] * tz; 8528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[3][2] += m_matrix[3][3] * tz; 8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 8568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 8578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::skew(double sx, double sy) 8598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 8608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // angles are in degrees. Switch to radians 8618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian sx = deg2rad(sx); 8628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian sy = deg2rad(sy); 8638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix mat; 8658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[0][1] = tan(sy); // note that the y shear goes in the first row 8668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[1][0] = tan(sx); // and the x shear in the second row 8678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(mat); 8698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 8708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::applyPerspective(double p) 8738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 8748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix mat; 8758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (p != 0) 8768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian mat.m_matrix[2][3] = -1/p; 8778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(mat); 8798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 8808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 8818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochTransformationMatrix TransformationMatrix::rectToRect(const FloatRect& from, const FloatRect& to) 8830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 8840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(!from.isEmpty()); 8850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return TransformationMatrix(to.width() / from.width(), 8860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 0, 0, 8870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch to.height() / from.height(), 8880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch to.x() - from.x(), 8890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch to.y() - from.y()); 8900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 8910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 8938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// *this = mat * *this 8948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// 8952fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockTransformationMatrix& TransformationMatrix::multiply(const TransformationMatrix& mat) 8968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 8978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Matrix4 tmp; 8988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 8998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[0][0] = (mat.m_matrix[0][0] * m_matrix[0][0] + mat.m_matrix[0][1] * m_matrix[1][0] 9008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[0][2] * m_matrix[2][0] + mat.m_matrix[0][3] * m_matrix[3][0]); 9018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[0][1] = (mat.m_matrix[0][0] * m_matrix[0][1] + mat.m_matrix[0][1] * m_matrix[1][1] 9028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[0][2] * m_matrix[2][1] + mat.m_matrix[0][3] * m_matrix[3][1]); 9038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[0][2] = (mat.m_matrix[0][0] * m_matrix[0][2] + mat.m_matrix[0][1] * m_matrix[1][2] 9048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[0][2] * m_matrix[2][2] + mat.m_matrix[0][3] * m_matrix[3][2]); 9058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[0][3] = (mat.m_matrix[0][0] * m_matrix[0][3] + mat.m_matrix[0][1] * m_matrix[1][3] 9068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[0][2] * m_matrix[2][3] + mat.m_matrix[0][3] * m_matrix[3][3]); 9078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[1][0] = (mat.m_matrix[1][0] * m_matrix[0][0] + mat.m_matrix[1][1] * m_matrix[1][0] 9098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[1][2] * m_matrix[2][0] + mat.m_matrix[1][3] * m_matrix[3][0]); 9108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[1][1] = (mat.m_matrix[1][0] * m_matrix[0][1] + mat.m_matrix[1][1] * m_matrix[1][1] 9118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[1][2] * m_matrix[2][1] + mat.m_matrix[1][3] * m_matrix[3][1]); 9128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[1][2] = (mat.m_matrix[1][0] * m_matrix[0][2] + mat.m_matrix[1][1] * m_matrix[1][2] 9138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[1][2] * m_matrix[2][2] + mat.m_matrix[1][3] * m_matrix[3][2]); 9148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[1][3] = (mat.m_matrix[1][0] * m_matrix[0][3] + mat.m_matrix[1][1] * m_matrix[1][3] 9158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[1][2] * m_matrix[2][3] + mat.m_matrix[1][3] * m_matrix[3][3]); 9168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[2][0] = (mat.m_matrix[2][0] * m_matrix[0][0] + mat.m_matrix[2][1] * m_matrix[1][0] 9188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[2][2] * m_matrix[2][0] + mat.m_matrix[2][3] * m_matrix[3][0]); 9198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[2][1] = (mat.m_matrix[2][0] * m_matrix[0][1] + mat.m_matrix[2][1] * m_matrix[1][1] 9208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[2][2] * m_matrix[2][1] + mat.m_matrix[2][3] * m_matrix[3][1]); 9218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[2][2] = (mat.m_matrix[2][0] * m_matrix[0][2] + mat.m_matrix[2][1] * m_matrix[1][2] 9228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[2][2] * m_matrix[2][2] + mat.m_matrix[2][3] * m_matrix[3][2]); 9238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[2][3] = (mat.m_matrix[2][0] * m_matrix[0][3] + mat.m_matrix[2][1] * m_matrix[1][3] 9248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[2][2] * m_matrix[2][3] + mat.m_matrix[2][3] * m_matrix[3][3]); 9258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[3][0] = (mat.m_matrix[3][0] * m_matrix[0][0] + mat.m_matrix[3][1] * m_matrix[1][0] 9278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[3][2] * m_matrix[2][0] + mat.m_matrix[3][3] * m_matrix[3][0]); 9288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[3][1] = (mat.m_matrix[3][0] * m_matrix[0][1] + mat.m_matrix[3][1] * m_matrix[1][1] 9298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[3][2] * m_matrix[2][1] + mat.m_matrix[3][3] * m_matrix[3][1]); 9308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[3][2] = (mat.m_matrix[3][0] * m_matrix[0][2] + mat.m_matrix[3][1] * m_matrix[1][2] 9318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[3][2] * m_matrix[2][2] + mat.m_matrix[3][3] * m_matrix[3][2]); 9328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp[3][3] = (mat.m_matrix[3][0] * m_matrix[0][3] + mat.m_matrix[3][1] * m_matrix[1][3] 9338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian + mat.m_matrix[3][2] * m_matrix[2][3] + mat.m_matrix[3][3] * m_matrix[3][3]); 9348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian setMatrix(tmp); 9368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return *this; 9378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 9388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::multVecMatrix(double x, double y, double& resultX, double& resultY) const 9408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 9418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0]; 9428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1]; 9438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3]; 9448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (w != 1 && w != 0) { 9458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultX /= w; 9468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultY /= w; 9478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 9488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 9498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::multVecMatrix(double x, double y, double z, double& resultX, double& resultY, double& resultZ) const 9518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 9528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0] + z * m_matrix[2][0]; 9538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1] + z * m_matrix[2][1]; 9548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultZ = m_matrix[3][2] + x * m_matrix[0][2] + y * m_matrix[1][2] + z * m_matrix[2][2]; 9558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3] + z * m_matrix[2][3]; 9568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (w != 1 && w != 0) { 9578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultX /= w; 9588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultY /= w; 9598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian resultZ /= w; 9608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 9618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 9628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool TransformationMatrix::isInvertible() const 9648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 9655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (isIdentityOrTranslation()) 9665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return true; 9675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 9688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double det = WebCore::determinant4x4(m_matrix); 9698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (fabs(det) < SMALL_NUMBER) 9718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return false; 9728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return true; 9748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 9758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix TransformationMatrix::inverse() const 9778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 9785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (isIdentityOrTranslation()) { 9795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // identity matrix 9805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0) 9815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return TransformationMatrix(); 9825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 9835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // translation 9845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return TransformationMatrix(1, 0, 0, 0, 9855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 0, 1, 0, 0, 9865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 0, 0, 1, 0, 9875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian -m_matrix[3][0], -m_matrix[3][1], -m_matrix[3][2], 1); 9885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 9898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian TransformationMatrix invMat; 9918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bool inverted = WebCore::inverse(m_matrix, invMat.m_matrix); 9928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!inverted) 9938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return TransformationMatrix(); 9948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return invMat; 9968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 9978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::makeAffine() 9998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 10008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[0][2] = 0; 10018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[0][3] = 0; 10028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[1][2] = 0; 10048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[1][3] = 0; 10058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[2][0] = 0; 10078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[2][1] = 0; 10088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[2][2] = 1; 10098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[2][3] = 0; 10108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[3][2] = 0; 10128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[3][3] = 1; 10138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 10148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10158a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockAffineTransform TransformationMatrix::toAffineTransform() const 10168a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{ 10178a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return AffineTransform(m_matrix[0][0], m_matrix[0][1], m_matrix[1][0], 10188a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block m_matrix[1][1], m_matrix[3][0], m_matrix[3][1]); 10198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block} 10208a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 10218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic inline void blendFloat(double& from, double to, double progress) 10228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 10238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (from != to) 10248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian from = from + (to - from) * progress; 10258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 10268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::blend(const TransformationMatrix& from, double progress) 10288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 10298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (from.isIdentity() && isIdentity()) 10308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 10318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // decompose 10338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian DecomposedType fromDecomp; 10348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian DecomposedType toDecomp; 10358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian from.decompose(fromDecomp); 10368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian decompose(toDecomp); 10378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // interpolate 10398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress); 10408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.scaleY, toDecomp.scaleY, progress); 10418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.scaleZ, toDecomp.scaleZ, progress); 10428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.skewXY, toDecomp.skewXY, progress); 10438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.skewXZ, toDecomp.skewXZ, progress); 10448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.skewYZ, toDecomp.skewYZ, progress); 10458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.translateX, toDecomp.translateX, progress); 10468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.translateY, toDecomp.translateY, progress); 10478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.translateZ, toDecomp.translateZ, progress); 10488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.perspectiveX, toDecomp.perspectiveX, progress); 10498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.perspectiveY, toDecomp.perspectiveY, progress); 10508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.perspectiveZ, toDecomp.perspectiveZ, progress); 10518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blendFloat(fromDecomp.perspectiveW, toDecomp.perspectiveW, progress); 10528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian slerp(&fromDecomp.quaternionX, &toDecomp.quaternionX, progress); 10548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // recompose 10568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian recompose(fromDecomp); 10578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 10588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool TransformationMatrix::decompose(DecomposedType& decomp) const 10608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 10618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isIdentity()) { 10628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian memset(&decomp, 0, sizeof(decomp)); 10638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian decomp.perspectiveW = 1; 10648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian decomp.scaleX = 1; 10658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian decomp.scaleY = 1; 10668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian decomp.scaleZ = 1; 10678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 10688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!WebCore::decompose(m_matrix, decomp)) 10708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return false; 10718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return true; 10728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 10738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::recompose(const DecomposedType& decomp) 10758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 10768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian makeIdentity(); 10778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // first apply perspective 10798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[0][3] = (float) decomp.perspectiveX; 10808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[1][3] = (float) decomp.perspectiveY; 10818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[2][3] = (float) decomp.perspectiveZ; 10828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix[3][3] = (float) decomp.perspectiveW; 10838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // now translate 10858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian translate3d((float) decomp.translateX, (float) decomp.translateY, (float) decomp.translateZ); 10868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // apply rotation 10888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double xx = decomp.quaternionX * decomp.quaternionX; 10898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double xy = decomp.quaternionX * decomp.quaternionY; 10908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double xz = decomp.quaternionX * decomp.quaternionZ; 10918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double xw = decomp.quaternionX * decomp.quaternionW; 10928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double yy = decomp.quaternionY * decomp.quaternionY; 10938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double yz = decomp.quaternionY * decomp.quaternionZ; 10948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double yw = decomp.quaternionY * decomp.quaternionW; 10958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double zz = decomp.quaternionZ * decomp.quaternionZ; 10968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian double zw = decomp.quaternionZ * decomp.quaternionW; 10978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 10988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Construct a composite rotation matrix from the quaternion values 10998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix rotationMatrix(1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0, 11008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw), 0, 11018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0, 11028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 0, 0, 0, 1); 11038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 11042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(rotationMatrix); 11058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 11068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // now apply skew 11078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (decomp.skewYZ) { 11088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix tmp; 11098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp.setM32((float) decomp.skewYZ); 11102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(tmp); 11118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 11128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 11138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (decomp.skewXZ) { 11148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix tmp; 11158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp.setM31((float) decomp.skewXZ); 11162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(tmp); 11178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 11188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 11198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (decomp.skewXY) { 11208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TransformationMatrix tmp; 11218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian tmp.setM21((float) decomp.skewXY); 11222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block multiply(tmp); 11238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 11248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 11258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // finally, apply scale 11268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian scale3d((float) decomp.scaleX, (float) decomp.scaleY, (float) decomp.scaleZ); 11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1130