📄 transformationmatrix.cpp
字号:
TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, double rz){ // angles are in degrees. Switch to radians rx = deg2rad(rx); ry = deg2rad(ry); rz = deg2rad(rz); TransformationMatrix mat; rz /= 2.0f; double sinA = sin(rz); double cosA = cos(rz); double sinA2 = sinA * sinA; mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2; mat.m_matrix[0][1] = 2.0f * sinA * cosA; mat.m_matrix[0][2] = 0.0f; mat.m_matrix[1][0] = -2.0f * sinA * cosA; mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2; mat.m_matrix[1][2] = 0.0f; mat.m_matrix[2][0] = 0.0f; mat.m_matrix[2][1] = 0.0f; mat.m_matrix[2][2] = 1.0f; mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; mat.m_matrix[3][3] = 1.0f; TransformationMatrix rmat(mat); ry /= 2.0f; sinA = sin(ry); cosA = cos(ry); sinA2 = sinA * sinA; mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2; mat.m_matrix[0][1] = 0.0f; mat.m_matrix[0][2] = -2.0f * sinA * cosA; mat.m_matrix[1][0] = 0.0f; mat.m_matrix[1][1] = 1.0f; mat.m_matrix[1][2] = 0.0f; mat.m_matrix[2][0] = 2.0f * sinA * cosA; mat.m_matrix[2][1] = 0.0f; mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2; mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; mat.m_matrix[3][3] = 1.0f; rmat.multLeft(mat); rx /= 2.0f; sinA = sin(rx); cosA = cos(rx); sinA2 = sinA * sinA; mat.m_matrix[0][0] = 1.0f; mat.m_matrix[0][1] = 0.0f; mat.m_matrix[0][2] = 0.0f; mat.m_matrix[1][0] = 0.0f; mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2; mat.m_matrix[1][2] = 2.0f * sinA * cosA; mat.m_matrix[2][0] = 0.0f; mat.m_matrix[2][1] = -2.0f * sinA * cosA; mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2; mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; mat.m_matrix[3][3] = 1.0f; rmat.multLeft(mat); multLeft(rmat); return *this;}TransformationMatrix& TransformationMatrix::translate(double tx, double ty){ // FIXME: optimize to avoid matrix copy TransformationMatrix mat; mat.m_matrix[3][0] = tx; mat.m_matrix[3][1] = ty; multLeft(mat); return *this;}TransformationMatrix& TransformationMatrix::translate3d(double tx, double ty, double tz){ // FIXME: optimize to avoid matrix copy TransformationMatrix mat; mat.m_matrix[3][0] = tx; mat.m_matrix[3][1] = ty; mat.m_matrix[3][2] = tz; multLeft(mat); return *this;}TransformationMatrix& TransformationMatrix::translateRight(double tx, double ty){ if (tx != 0) { m_matrix[0][0] += m_matrix[0][3] * tx; m_matrix[1][0] += m_matrix[1][3] * tx; m_matrix[2][0] += m_matrix[2][3] * tx; m_matrix[3][0] += m_matrix[3][3] * tx; } if (ty != 0) { m_matrix[0][1] += m_matrix[0][3] * ty; m_matrix[1][1] += m_matrix[1][3] * ty; m_matrix[2][1] += m_matrix[2][3] * ty; m_matrix[3][1] += m_matrix[3][3] * ty; } return *this;}TransformationMatrix& TransformationMatrix::translateRight3d(double tx, double ty, double tz){ translateRight(tx, ty); if (tz != 0) { m_matrix[0][2] += m_matrix[0][3] * tz; m_matrix[1][2] += m_matrix[1][3] * tz; m_matrix[2][2] += m_matrix[2][3] * tz; m_matrix[3][2] += m_matrix[3][3] * tz; } return *this;}TransformationMatrix& TransformationMatrix::skew(double sx, double sy){ // angles are in degrees. Switch to radians sx = deg2rad(sx); sy = deg2rad(sy); TransformationMatrix mat; mat.m_matrix[0][1] = tan(sy); // note that the y shear goes in the first row mat.m_matrix[1][0] = tan(sx); // and the x shear in the second row multLeft(mat); return *this;}TransformationMatrix& TransformationMatrix::applyPerspective(double p){ TransformationMatrix mat; if (p != 0) mat.m_matrix[2][3] = -1/p; multLeft(mat); return *this;}//// *this = mat * *this//TransformationMatrix& TransformationMatrix::multLeft(const TransformationMatrix& mat){ Matrix4 tmp; tmp[0][0] = (mat.m_matrix[0][0] * m_matrix[0][0] + mat.m_matrix[0][1] * m_matrix[1][0] + mat.m_matrix[0][2] * m_matrix[2][0] + mat.m_matrix[0][3] * m_matrix[3][0]); tmp[0][1] = (mat.m_matrix[0][0] * m_matrix[0][1] + mat.m_matrix[0][1] * m_matrix[1][1] + mat.m_matrix[0][2] * m_matrix[2][1] + mat.m_matrix[0][3] * m_matrix[3][1]); tmp[0][2] = (mat.m_matrix[0][0] * m_matrix[0][2] + mat.m_matrix[0][1] * m_matrix[1][2] + mat.m_matrix[0][2] * m_matrix[2][2] + mat.m_matrix[0][3] * m_matrix[3][2]); tmp[0][3] = (mat.m_matrix[0][0] * m_matrix[0][3] + mat.m_matrix[0][1] * m_matrix[1][3] + mat.m_matrix[0][2] * m_matrix[2][3] + mat.m_matrix[0][3] * m_matrix[3][3]); tmp[1][0] = (mat.m_matrix[1][0] * m_matrix[0][0] + mat.m_matrix[1][1] * m_matrix[1][0] + mat.m_matrix[1][2] * m_matrix[2][0] + mat.m_matrix[1][3] * m_matrix[3][0]); tmp[1][1] = (mat.m_matrix[1][0] * m_matrix[0][1] + mat.m_matrix[1][1] * m_matrix[1][1] + mat.m_matrix[1][2] * m_matrix[2][1] + mat.m_matrix[1][3] * m_matrix[3][1]); tmp[1][2] = (mat.m_matrix[1][0] * m_matrix[0][2] + mat.m_matrix[1][1] * m_matrix[1][2] + mat.m_matrix[1][2] * m_matrix[2][2] + mat.m_matrix[1][3] * m_matrix[3][2]); tmp[1][3] = (mat.m_matrix[1][0] * m_matrix[0][3] + mat.m_matrix[1][1] * m_matrix[1][3] + mat.m_matrix[1][2] * m_matrix[2][3] + mat.m_matrix[1][3] * m_matrix[3][3]); tmp[2][0] = (mat.m_matrix[2][0] * m_matrix[0][0] + mat.m_matrix[2][1] * m_matrix[1][0] + mat.m_matrix[2][2] * m_matrix[2][0] + mat.m_matrix[2][3] * m_matrix[3][0]); tmp[2][1] = (mat.m_matrix[2][0] * m_matrix[0][1] + mat.m_matrix[2][1] * m_matrix[1][1] + mat.m_matrix[2][2] * m_matrix[2][1] + mat.m_matrix[2][3] * m_matrix[3][1]); tmp[2][2] = (mat.m_matrix[2][0] * m_matrix[0][2] + mat.m_matrix[2][1] * m_matrix[1][2] + mat.m_matrix[2][2] * m_matrix[2][2] + mat.m_matrix[2][3] * m_matrix[3][2]); tmp[2][3] = (mat.m_matrix[2][0] * m_matrix[0][3] + mat.m_matrix[2][1] * m_matrix[1][3] + mat.m_matrix[2][2] * m_matrix[2][3] + mat.m_matrix[2][3] * m_matrix[3][3]); tmp[3][0] = (mat.m_matrix[3][0] * m_matrix[0][0] + mat.m_matrix[3][1] * m_matrix[1][0] + mat.m_matrix[3][2] * m_matrix[2][0] + mat.m_matrix[3][3] * m_matrix[3][0]); tmp[3][1] = (mat.m_matrix[3][0] * m_matrix[0][1] + mat.m_matrix[3][1] * m_matrix[1][1] + mat.m_matrix[3][2] * m_matrix[2][1] + mat.m_matrix[3][3] * m_matrix[3][1]); tmp[3][2] = (mat.m_matrix[3][0] * m_matrix[0][2] + mat.m_matrix[3][1] * m_matrix[1][2] + mat.m_matrix[3][2] * m_matrix[2][2] + mat.m_matrix[3][3] * m_matrix[3][2]); tmp[3][3] = (mat.m_matrix[3][0] * m_matrix[0][3] + mat.m_matrix[3][1] * m_matrix[1][3] + mat.m_matrix[3][2] * m_matrix[2][3] + mat.m_matrix[3][3] * m_matrix[3][3]); setMatrix(tmp); return *this;}void TransformationMatrix::multVecMatrix(double x, double y, double& resultX, double& resultY) const{ resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0]; resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1]; double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3]; if (w != 1 && w != 0) { resultX /= w; resultY /= w; }}void TransformationMatrix::multVecMatrix(double x, double y, double z, double& resultX, double& resultY, double& resultZ) const{ resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0] + z * m_matrix[2][0]; resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1] + z * m_matrix[2][1]; resultZ = m_matrix[3][2] + x * m_matrix[0][2] + y * m_matrix[1][2] + z * m_matrix[2][2]; double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3] + z * m_matrix[2][3]; if (w != 1 && w != 0) { resultX /= w; resultY /= w; resultZ /= w; }}bool TransformationMatrix::isInvertible() const{ double det = WebCore::determinant4x4(m_matrix); if (fabs(det) < SMALL_NUMBER) return false; return true;}TransformationMatrix TransformationMatrix::inverse() const { TransformationMatrix invMat; bool inverted = WebCore::inverse(m_matrix, invMat.m_matrix); if (!inverted) return TransformationMatrix(); return invMat;}static inline void blendFloat(double& from, double to, double progress){ if (from != to) from = from + (to - from) * progress;}void TransformationMatrix::blend(const TransformationMatrix& from, double progress){ if (from.isIdentity() && isIdentity()) return; // decompose DecomposedType fromDecomp; DecomposedType toDecomp; from.decompose(fromDecomp); decompose(toDecomp); // interpolate blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress); blendFloat(fromDecomp.scaleY, toDecomp.scaleY, progress); blendFloat(fromDecomp.scaleZ, toDecomp.scaleZ, progress); blendFloat(fromDecomp.skewXY, toDecomp.skewXY, progress); blendFloat(fromDecomp.skewXZ, toDecomp.skewXZ, progress); blendFloat(fromDecomp.skewYZ, toDecomp.skewYZ, progress); blendFloat(fromDecomp.translateX, toDecomp.translateX, progress); blendFloat(fromDecomp.translateY, toDecomp.translateY, progress); blendFloat(fromDecomp.translateZ, toDecomp.translateZ, progress); blendFloat(fromDecomp.perspectiveX, toDecomp.perspectiveX, progress); blendFloat(fromDecomp.perspectiveY, toDecomp.perspectiveY, progress); blendFloat(fromDecomp.perspectiveZ, toDecomp.perspectiveZ, progress); blendFloat(fromDecomp.perspectiveW, toDecomp.perspectiveW, progress); slerp(&fromDecomp.quaternionX, &toDecomp.quaternionX, progress); // recompose recompose(fromDecomp);}bool TransformationMatrix::decompose(DecomposedType& decomp) const{ if (isIdentity()) { memset(&decomp, 0, sizeof(decomp)); decomp.perspectiveW = 1; decomp.scaleX = 1; decomp.scaleY = 1; decomp.scaleZ = 1; } if (!WebCore::decompose(m_matrix, decomp)) return false; return true;}void TransformationMatrix::recompose(const DecomposedType& decomp){ makeIdentity(); // first apply perspective m_matrix[0][3] = (float) decomp.perspectiveX; m_matrix[1][3] = (float) decomp.perspectiveY; m_matrix[2][3] = (float) decomp.perspectiveZ; m_matrix[3][3] = (float) decomp.perspectiveW; // now translate translate3d((float) decomp.translateX, (float) decomp.translateY, (float) decomp.translateZ); // apply rotation double xx = decomp.quaternionX * decomp.quaternionX; double xy = decomp.quaternionX * decomp.quaternionY; double xz = decomp.quaternionX * decomp.quaternionZ; double xw = decomp.quaternionX * decomp.quaternionW; double yy = decomp.quaternionY * decomp.quaternionY; double yz = decomp.quaternionY * decomp.quaternionZ; double yw = decomp.quaternionY * decomp.quaternionW; double zz = decomp.quaternionZ * decomp.quaternionZ; double zw = decomp.quaternionZ * decomp.quaternionW; // Construct a composite rotation matrix from the quaternion values TransformationMatrix rotationMatrix(1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0, 2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw), 0, 2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0, 0, 0, 0, 1); multLeft(rotationMatrix); // now apply skew if (decomp.skewYZ) { TransformationMatrix tmp; tmp.setM32((float) decomp.skewYZ); multLeft(tmp); } if (decomp.skewXZ) { TransformationMatrix tmp; tmp.setM31((float) decomp.skewXZ); multLeft(tmp); } if (decomp.skewXY) { TransformationMatrix tmp; tmp.setM21((float) decomp.skewXY); multLeft(tmp); } // finally, apply scale scale3d((float) decomp.scaleX, (float) decomp.scaleY, (float) decomp.scaleZ);}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -