Edit C:\Program Files\Java\jdk1.8.0_121\com\sun\javafx\geom\transform\GeneralTransform3D.java
/* * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sun.javafx.geom.transform; import com.sun.javafx.geom.BaseBounds; import com.sun.javafx.geom.Point2D; import com.sun.javafx.geom.Vec3d; import com.sun.javafx.geom.Vec3f; /** * A general-purpose 4x4 transform that may or may not be affine. The * GeneralTransform is typically used only for projection transforms. * */ public final class GeneralTransform3D implements CanTransformVec3d { //The 4x4 double-precision floating point matrix. The mathematical //representation is row major, as in traditional matrix mathematics. protected double[] mat = new double[16]; //flag if this is an identity transformation. private boolean identity; /** * Constructs and initializes a transform to the identity matrix. */ public GeneralTransform3D() { setIdentity(); } /** * Returns true if the transform is affine. A transform is considered * to be affine if the last row of its matrix is (0,0,0,1). Note that * an instance of AffineTransform3D is always affine. */ public boolean isAffine() { if (!isInfOrNaN() && almostZero(mat[12]) && almostZero(mat[13]) && almostZero(mat[14]) && almostOne(mat[15])) { return true; } else { return false; } } /** * Sets the value of this transform to the specified transform. * * @param t1 the transform to copy into this transform. * * @return this transform */ public GeneralTransform3D set(GeneralTransform3D t1) { System.arraycopy(t1.mat, 0, mat, 0, mat.length); updateState(); return this; } /** * Sets the matrix values of this transform to the values in the * specified array. * * @param m an array of 16 values to copy into this transform in * row major order. * * @return this transform */ public GeneralTransform3D set(double[] m) { System.arraycopy(m, 0, mat, 0, mat.length); updateState(); return this; } /** * Returns a copy of an array of 16 values that contains the 4x4 matrix * of this transform. The first four elements of the array will contain * the top row of the transform matrix, etc. * * @param rv the return value, or null * * @return an array of 16 values */ public double[] get(double[] rv) { if (rv == null) { rv = new double[mat.length]; } System.arraycopy(mat, 0, rv, 0, mat.length); return rv; } public double get(int index) { assert ((index >= 0) && (index < mat.length)); return mat[index]; } private Vec3d tempV3d; public BaseBounds transform(BaseBounds src, BaseBounds dst) { if (tempV3d == null) { tempV3d = new Vec3d(); } return TransformHelper.general3dBoundsTransform(this, src, dst, tempV3d); } /** * Transform 2D point (with z == 0) * @param point * @param pointOut * @return */ public Point2D transform(Point2D point, Point2D pointOut) { if (pointOut == null) { pointOut = new Point2D(); } double w = (float) (mat[12] * point.x + mat[13] * point.y + mat[15]); pointOut.x = (float) (mat[0] * point.x + mat[1] * point.y + mat[3]); pointOut.y = (float) (mat[4] * point.x + mat[5] * point.y + mat[7]); pointOut.x /= w; pointOut.y /= w; return pointOut; } /** * Transforms the point parameter with this transform and * places the result into pointOut. The fourth element of the * point input paramter is assumed to be one. * * @param point the input point to be transformed * * @param pointOut the transformed point * * @return the transformed point */ public Vec3d transform(Vec3d point, Vec3d pointOut) { if (pointOut == null) { pointOut = new Vec3d(); } // compute here as point.x, point.y and point.z may change // in case (point == pointOut), and mat[14] is usually != 0 double w = (float) (mat[12] * point.x + mat[13] * point.y + mat[14] * point.z + mat[15]); pointOut.x = (float) (mat[0] * point.x + mat[1] * point.y + mat[2] * point.z + mat[3]); pointOut.y = (float) (mat[4] * point.x + mat[5] * point.y + mat[6] * point.z + mat[7]); pointOut.z = (float) (mat[8] * point.x + mat[9] * point.y + mat[10] * point.z + mat[11]); if (w != 0.0f) { pointOut.x /= w; pointOut.y /= w; pointOut.z /= w; } return pointOut; } /** * Transforms the point parameter with this transform and * places the result back into point. The fourth element of the * point input paramter is assumed to be one. * * @param point the input point to be transformed * * @return the transformed point */ public Vec3d transform(Vec3d point) { return transform(point, point); } /** * Transforms the normal parameter by this transform and places the value * into normalOut. The fourth element of the normal is assumed to be zero. * Note: For correct lighting results, if a transform has uneven scaling * surface normals should transformed by the inverse transpose of * the transform. This the responsibility of the application and is not * done automatically by this method. * * @param normal the input normal to be transformed * * @param normalOut the transformed normal * * @return the transformed normal */ public Vec3f transformNormal(Vec3f normal, Vec3f normalOut) { normal.x = (float) (mat[0]*normal.x + mat[1]*normal.y + mat[2]*normal.z); normal.y = (float) (mat[4]*normal.x + mat[5]*normal.y + mat[6]*normal.z); normal.z = (float) (mat[8]*normal.x + mat[9]*normal.y + mat[10]*normal.z); return normalOut; } /** * Transforms the normal parameter by this transform and places the value * back into normal. The fourth element of the normal is assumed to be zero. * Note: For correct lighting results, if a transform has uneven scaling * surface normals should transformed by the inverse transpose of * the transform. This the responsibility of the application and is not * done automatically by this method. * * @param normal the input normal to be transformed * * @return the transformed normal */ public Vec3f transformNormal(Vec3f normal) { return transformNormal(normal, normal); } /** * Sets the value of this transform to a perspective projection transform. * This transform maps points from Eye Coordinates (EC) * to Clipping Coordinates (CC). * Note that the field of view is specified in radians. * * @param verticalFOV specifies whether the fov is vertical (Y direction). * * @param fov specifies the field of view in radians * * @param aspect specifies the aspect ratio. The aspect ratio is the ratio * of width to height. * * @param zNear the distance to the frustum's near clipping plane. * This value must be positive, (the value -zNear is the location of the * near clip plane). * * @param zFar the distance to the frustum's far clipping plane * * @return this transform */ public GeneralTransform3D perspective(boolean verticalFOV, double fov, double aspect, double zNear, double zFar) { double sine; double cotangent; double deltaZ; double half_fov = fov * 0.5; deltaZ = zFar - zNear; sine = Math.sin(half_fov); cotangent = Math.cos(half_fov) / sine; mat[0] = verticalFOV ? cotangent / aspect : cotangent; mat[5] = verticalFOV ? cotangent : cotangent * aspect; mat[10] = -(zFar + zNear) / deltaZ; mat[11] = -2.0 * zNear * zFar / deltaZ; mat[14] = -1.0; mat[1] = mat[2] = mat[3] = mat[4] = mat[6] = mat[7] = mat[8] = mat[9] = mat[12] = mat[13] = mat[15] = 0; updateState(); return this; } /** * Sets the value of this transform to an orthographic (parallel) * projection transform. * This transform maps coordinates from Eye Coordinates (EC) * to Clipping Coordinates (CC). Note that unlike the similar function * in OpenGL, the clipping coordinates generated by the resulting * transform are in a right-handed coordinate system. * @param left the vertical line on the left edge of the near * clipping plane mapped to the left edge of the graphics window * @param right the vertical line on the right edge of the near * clipping plane mapped to the right edge of the graphics window * @param bottom the horizontal line on the bottom edge of the near * clipping plane mapped to the bottom edge of the graphics window * @param top the horizontal line on the top edge of the near * clipping plane mapped to the top edge of the graphics window * @param near the distance to the frustum's near clipping plane * (the value -near is the location of the near clip plane) * @param far the distance to the frustum's far clipping plane * * @return this transform */ public GeneralTransform3D ortho(double left, double right, double bottom, double top, double near, double far) { double deltax = 1 / (right - left); double deltay = 1 / (top - bottom); double deltaz = 1 / (far - near); mat[0] = 2.0 * deltax; mat[3] = -(right + left) * deltax; mat[5] = 2.0 * deltay; mat[7] = -(top + bottom) * deltay; mat[10] = 2.0 * deltaz; mat[11] = (far + near) * deltaz; mat[1] = mat[2] = mat[4] = mat[6] = mat[8] = mat[9] = mat[12] = mat[13] = mat[14] = 0; mat[15] = 1; updateState(); return this; } public double computeClipZCoord() { double zEc = (1.0 - mat[15]) / mat[14]; double zCc = mat[10] * zEc + mat[11]; return zCc; } /** * Computes the determinant of this transform. * * @return the determinant */ public double determinant() { // cofactor exapainsion along first row return mat[0]*(mat[5]*(mat[10]*mat[15] - mat[11]*mat[14]) - mat[6]*(mat[ 9]*mat[15] - mat[11]*mat[13]) + mat[7]*(mat[ 9]*mat[14] - mat[10]*mat[13])) - mat[1]*(mat[4]*(mat[10]*mat[15] - mat[11]*mat[14]) - mat[6]*(mat[ 8]*mat[15] - mat[11]*mat[12]) + mat[7]*(mat[ 8]*mat[14] - mat[10]*mat[12])) + mat[2]*(mat[4]*(mat[ 9]*mat[15] - mat[11]*mat[13]) - mat[5]*(mat[ 8]*mat[15] - mat[11]*mat[12]) + mat[7]*(mat[ 8]*mat[13] - mat[ 9]*mat[12])) - mat[3]*(mat[4]*(mat[ 9]*mat[14] - mat[10]*mat[13]) - mat[5]*(mat[ 8]*mat[14] - mat[10]*mat[12]) + mat[6]*(mat[ 8]*mat[13] - mat[ 9]*mat[12])); } /** * Inverts this transform in place. * * @return this transform */ public GeneralTransform3D invert() { return invert(this); } /** * General invert routine. Inverts t1 and places the result in "this". * Note that this routine handles both the "this" version and the * non-"this" version. * * Also note that since this routine is slow anyway, we won't worry * about allocating a little bit of garbage. */ private GeneralTransform3D invert(GeneralTransform3D t1) { double[] tmp = new double[16]; int[] row_perm = new int[4]; // Use LU decomposition and backsubstitution code specifically // for floating-point 4x4 matrices. // Copy source matrix to tmp System.arraycopy(t1.mat, 0, tmp, 0, tmp.length); // Calculate LU decomposition: Is the matrix singular? if (!luDecomposition(tmp, row_perm)) { // Matrix has no inverse throw new SingularMatrixException(); } // Perform back substitution on the identity matrix // luDecomposition will set rot[] & scales[] for use // in luBacksubstituation mat[0] = 1.0; mat[1] = 0.0; mat[2] = 0.0; mat[3] = 0.0; mat[4] = 0.0; mat[5] = 1.0; mat[6] = 0.0; mat[7] = 0.0; mat[8] = 0.0; mat[9] = 0.0; mat[10] = 1.0; mat[11] = 0.0; mat[12] = 0.0; mat[13] = 0.0; mat[14] = 0.0; mat[15] = 1.0; luBacksubstitution(tmp, row_perm, this.mat); updateState(); return this; } /** * Given a 4x4 array "matrix0", this function replaces it with the * LU decomposition of a row-wise permutation of itself. The input * parameters are "matrix0" and "dimen". The array "matrix0" is also * an output parameter. The vector "row_perm[4]" is an output * parameter that contains the row permutations resulting from partial * pivoting. The output parameter "even_row_xchg" is 1 when the * number of row exchanges is even, or -1 otherwise. Assumes data * type is always double. * * This function is similar to luDecomposition, except that it * is tuned specifically for 4x4 matrices. * * @return true if the matrix is nonsingular, or false otherwise. */ private static boolean luDecomposition(double[] matrix0, int[] row_perm) { // Reference: Press, Flannery, Teukolsky, Vetterling, // _Numerical_Recipes_in_C_, Cambridge University Press, // 1988, pp 40-45. // // Can't re-use this temporary since the method is static. double row_scale[] = new double[4]; // Determine implicit scaling information by looping over rows { int i, j; int ptr, rs; double big, temp; ptr = 0; rs = 0; // For each row ... i = 4; while (i-- != 0) { big = 0.0; // For each column, find the largest element in the row j = 4; while (j-- != 0) { temp = matrix0[ptr++]; temp = Math.abs(temp); if (temp > big) { big = temp; } } // Is the matrix singular? if (big == 0.0) { return false; } row_scale[rs++] = 1.0 / big; } } { int j; int mtx; mtx = 0; // For all columns, execute Crout's method for (j = 0; j < 4; j++) { int i, imax, k; int target, p1, p2; double sum, big, temp; // Determine elements of upper diagonal matrix U for (i = 0; i < j; i++) { target = mtx + (4*i) + j; sum = matrix0[target]; k = i; p1 = mtx + (4*i); p2 = mtx + j; while (k-- != 0) { sum -= matrix0[p1] * matrix0[p2]; p1++; p2 += 4; } matrix0[target] = sum; } // Search for largest pivot element and calculate // intermediate elements of lower diagonal matrix L. big = 0.0; imax = -1; for (i = j; i < 4; i++) { target = mtx + (4*i) + j; sum = matrix0[target]; k = j; p1 = mtx + (4*i); p2 = mtx + j; while (k-- != 0) { sum -= matrix0[p1] * matrix0[p2]; p1++; p2 += 4; } matrix0[target] = sum; // Is this the best pivot so far? if ((temp = row_scale[i] * Math.abs(sum)) >= big) { big = temp; imax = i; } } if (imax < 0) { return false; } // Is a row exchange necessary? if (j != imax) { // Yes: exchange rows k = 4; p1 = mtx + (4*imax); p2 = mtx + (4*j); while (k-- != 0) { temp = matrix0[p1]; matrix0[p1++] = matrix0[p2]; matrix0[p2++] = temp; } // Record change in scale factor row_scale[imax] = row_scale[j]; } // Record row permutation row_perm[j] = imax; // Is the matrix singular if (matrix0[(mtx + (4*j) + j)] == 0.0) { return false; } // Divide elements of lower diagonal matrix L by pivot if (j != (4-1)) { temp = 1.0 / (matrix0[(mtx + (4*j) + j)]); target = mtx + (4*(j+1)) + j; i = 3 - j; while (i-- != 0) { matrix0[target] *= temp; target += 4; } } } } return true; } /** * Solves a set of linear equations. The input parameters "matrix1", * and "row_perm" come from luDecompostionD4x4 and do not change * here. The parameter "matrix2" is a set of column vectors assembled * into a 4x4 matrix of floating-point values. The procedure takes each * column of "matrix2" in turn and treats it as the right-hand side of the * matrix equation Ax = LUx = b. The solution vector replaces the * original column of the matrix. * * If "matrix2" is the identity matrix, the procedure replaces its contents * with the inverse of the matrix from which "matrix1" was originally * derived. */ // // Reference: Press, Flannery, Teukolsky, Vetterling, // _Numerical_Recipes_in_C_, Cambridge University Press, // 1988, pp 44-45. // private static void luBacksubstitution(double[] matrix1, int[] row_perm, double[] matrix2) { int i, ii, ip, j, k; int rp; int cv, rv; // rp = row_perm; rp = 0; // For each column vector of matrix2 ... for (k = 0; k < 4; k++) { // cv = &(matrix2[0][k]); cv = k; ii = -1; // Forward substitution for (i = 0; i < 4; i++) { double sum; ip = row_perm[rp+i]; sum = matrix2[cv+4*ip]; matrix2[cv+4*ip] = matrix2[cv+4*i]; if (ii >= 0) { // rv = &(matrix1[i][0]); rv = i*4; for (j = ii; j <= i-1; j++) { sum -= matrix1[rv+j] * matrix2[cv+4*j]; } } else if (sum != 0.0) { ii = i; } matrix2[cv+4*i] = sum; } // Backsubstitution // rv = &(matrix1[3][0]); rv = 3*4; matrix2[cv+4*3] /= matrix1[rv+3]; rv -= 4; matrix2[cv+4*2] = (matrix2[cv+4*2] - matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+2]; rv -= 4; matrix2[cv+4*1] = (matrix2[cv+4*1] - matrix1[rv+2] * matrix2[cv+4*2] - matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+1]; rv -= 4; matrix2[cv+4*0] = (matrix2[cv+4*0] - matrix1[rv+1] * matrix2[cv+4*1] - matrix1[rv+2] * matrix2[cv+4*2] - matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+0]; } } /** * Sets the value of this transform to the result of multiplying itself * with transform t1 : this = this * t1. * * @param t1 the other transform * * @return this transform */ public GeneralTransform3D mul(BaseTransform t1) { if (t1.isIdentity()) { return this; } double tmp0, tmp1, tmp2, tmp3; double tmp4, tmp5, tmp6, tmp7; double tmp8, tmp9, tmp10, tmp11; double tmp12, tmp13, tmp14, tmp15; double mxx = t1.getMxx(); double mxy = t1.getMxy(); double mxz = t1.getMxz(); double mxt = t1.getMxt(); double myx = t1.getMyx(); double myy = t1.getMyy(); double myz = t1.getMyz(); double myt = t1.getMyt(); double mzx = t1.getMzx(); double mzy = t1.getMzy(); double mzz = t1.getMzz(); double mzt = t1.getMzt(); tmp0 = mat[0] * mxx + mat[1] * myx + mat[2] * mzx; tmp1 = mat[0] * mxy + mat[1] * myy + mat[2] * mzy; tmp2 = mat[0] * mxz + mat[1] * myz + mat[2] * mzz; tmp3 = mat[0] * mxt + mat[1] * myt + mat[2] * mzt + mat[3]; tmp4 = mat[4] * mxx + mat[5] * myx + mat[6] * mzx; tmp5 = mat[4] * mxy + mat[5] * myy + mat[6] * mzy; tmp6 = mat[4] * mxz + mat[5] * myz + mat[6] * mzz; tmp7 = mat[4] * mxt + mat[5] * myt + mat[6] * mzt + mat[7]; tmp8 = mat[8] * mxx + mat[9] * myx + mat[10] * mzx; tmp9 = mat[8] * mxy + mat[9] * myy + mat[10] * mzy; tmp10 = mat[8] * mxz + mat[9] * myz + mat[10] * mzz; tmp11 = mat[8] * mxt + mat[9] * myt + mat[10] * mzt + mat[11]; if (isAffine()) { tmp12 = tmp13 = tmp14 = 0; tmp15 = 1; } else { tmp12 = mat[12] * mxx + mat[13] * myx + mat[14] * mzx; tmp13 = mat[12] * mxy + mat[13] * myy + mat[14] * mzy; tmp14 = mat[12] * mxz + mat[13] * myz + mat[14] * mzz; tmp15 = mat[12] * mxt + mat[13] * myt + mat[14] * mzt + mat[15]; } mat[0] = tmp0; mat[1] = tmp1; mat[2] = tmp2; mat[3] = tmp3; mat[4] = tmp4; mat[5] = tmp5; mat[6] = tmp6; mat[7] = tmp7; mat[8] = tmp8; mat[9] = tmp9; mat[10] = tmp10; mat[11] = tmp11; mat[12] = tmp12; mat[13] = tmp13; mat[14] = tmp14; mat[15] = tmp15; updateState(); return this; } /** * Sets the value of this transform to the result of multiplying itself * with a scale transform: * <pre> * scaletx = * [ sx 0 0 0 ] * [ 0 sy 0 0 ] * [ 0 0 sz 0 ] * [ 0 0 0 1 ]. * this = this * scaletx. * </pre> * * @param sx the X coordinate scale factor * @param sy the Y coordinate scale factor * @param sz the Z coordinate scale factor * * @return this transform */ public GeneralTransform3D scale(double sx, double sy, double sz) { boolean update = false; if (sx != 1.0) { mat[0] *= sx; mat[4] *= sx; mat[8] *= sx; mat[12] *= sx; update = true; } if (sy != 1.0) { mat[1] *= sy; mat[5] *= sy; mat[9] *= sy; mat[13] *= sy; update = true; } if (sz != 1.0) { mat[2] *= sz; mat[6] *= sz; mat[10] *= sz; mat[14] *= sz; update = true; } if (update) { updateState(); } return this; } /** * Sets the value of this transform to the result of multiplying itself * with transform t1 : this = this * t1. * * @param t1 the other transform * * @return this transform */ public GeneralTransform3D mul(GeneralTransform3D t1) { if (t1.isIdentity()) { return this; } double tmp0, tmp1, tmp2, tmp3; double tmp4, tmp5, tmp6, tmp7; double tmp8, tmp9, tmp10, tmp11; double tmp12, tmp13, tmp14, tmp15; if (t1.isAffine()) { tmp0 = mat[0] * t1.mat[0] + mat[1] * t1.mat[4] + mat[2] * t1.mat[8]; tmp1 = mat[0] * t1.mat[1] + mat[1] * t1.mat[5] + mat[2] * t1.mat[9]; tmp2 = mat[0] * t1.mat[2] + mat[1] * t1.mat[6] + mat[2] * t1.mat[10]; tmp3 = mat[0] * t1.mat[3] + mat[1] * t1.mat[7] + mat[2] * t1.mat[11] + mat[3]; tmp4 = mat[4] * t1.mat[0] + mat[5] * t1.mat[4] + mat[6] * t1.mat[8]; tmp5 = mat[4] * t1.mat[1] + mat[5] * t1.mat[5] + mat[6] * t1.mat[9]; tmp6 = mat[4] * t1.mat[2] + mat[5] * t1.mat[6] + mat[6] * t1.mat[10]; tmp7 = mat[4] * t1.mat[3] + mat[5] * t1.mat[7] + mat[6] * t1.mat[11] + mat[7]; tmp8 = mat[8] * t1.mat[0] + mat[9] * t1.mat[4] + mat[10] * t1.mat[8]; tmp9 = mat[8] * t1.mat[1] + mat[9] * t1.mat[5] + mat[10] * t1.mat[9]; tmp10 = mat[8] * t1.mat[2] + mat[9] * t1.mat[6] + mat[10] * t1.mat[10]; tmp11 = mat[8] * t1.mat[3] + mat[9] * t1.mat[7] + mat[10] * t1.mat[11] + mat[11]; if (isAffine()) { tmp12 = tmp13 = tmp14 = 0; tmp15 = 1; } else { tmp12 = mat[12] * t1.mat[0] + mat[13] * t1.mat[4] + mat[14] * t1.mat[8]; tmp13 = mat[12] * t1.mat[1] + mat[13] * t1.mat[5] + mat[14] * t1.mat[9]; tmp14 = mat[12] * t1.mat[2] + mat[13] * t1.mat[6] + mat[14] * t1.mat[10]; tmp15 = mat[12] * t1.mat[3] + mat[13] * t1.mat[7] + mat[14] * t1.mat[11] + mat[15]; } } else { tmp0 = mat[0] * t1.mat[0] + mat[1] * t1.mat[4] + mat[2] * t1.mat[8] + mat[3] * t1.mat[12]; tmp1 = mat[0] * t1.mat[1] + mat[1] * t1.mat[5] + mat[2] * t1.mat[9] + mat[3] * t1.mat[13]; tmp2 = mat[0] * t1.mat[2] + mat[1] * t1.mat[6] + mat[2] * t1.mat[10] + mat[3] * t1.mat[14]; tmp3 = mat[0] * t1.mat[3] + mat[1] * t1.mat[7] + mat[2] * t1.mat[11] + mat[3] * t1.mat[15]; tmp4 = mat[4] * t1.mat[0] + mat[5] * t1.mat[4] + mat[6] * t1.mat[8] + mat[7] * t1.mat[12]; tmp5 = mat[4] * t1.mat[1] + mat[5] * t1.mat[5] + mat[6] * t1.mat[9] + mat[7] * t1.mat[13]; tmp6 = mat[4] * t1.mat[2] + mat[5] * t1.mat[6] + mat[6] * t1.mat[10] + mat[7] * t1.mat[14]; tmp7 = mat[4] * t1.mat[3] + mat[5] * t1.mat[7] + mat[6] * t1.mat[11] + mat[7] * t1.mat[15]; tmp8 = mat[8] * t1.mat[0] + mat[9] * t1.mat[4] + mat[10] * t1.mat[8] + mat[11] * t1.mat[12]; tmp9 = mat[8] * t1.mat[1] + mat[9] * t1.mat[5] + mat[10] * t1.mat[9] + mat[11] * t1.mat[13]; tmp10 = mat[8] * t1.mat[2] + mat[9] * t1.mat[6] + mat[10] * t1.mat[10] + mat[11] * t1.mat[14]; tmp11 = mat[8] * t1.mat[3] + mat[9] * t1.mat[7] + mat[10] * t1.mat[11] + mat[11] * t1.mat[15]; if (isAffine()) { tmp12 = t1.mat[12]; tmp13 = t1.mat[13]; tmp14 = t1.mat[14]; tmp15 = t1.mat[15]; } else { tmp12 = mat[12] * t1.mat[0] + mat[13] * t1.mat[4] + mat[14] * t1.mat[8] + mat[15] * t1.mat[12]; tmp13 = mat[12] * t1.mat[1] + mat[13] * t1.mat[5] + mat[14] * t1.mat[9] + mat[15] * t1.mat[13]; tmp14 = mat[12] * t1.mat[2] + mat[13] * t1.mat[6] + mat[14] * t1.mat[10] + mat[15] * t1.mat[14]; tmp15 = mat[12] * t1.mat[3] + mat[13] * t1.mat[7] + mat[14] * t1.mat[11] + mat[15] * t1.mat[15]; } } mat[0] = tmp0; mat[1] = tmp1; mat[2] = tmp2; mat[3] = tmp3; mat[4] = tmp4; mat[5] = tmp5; mat[6] = tmp6; mat[7] = tmp7; mat[8] = tmp8; mat[9] = tmp9; mat[10] = tmp10; mat[11] = tmp11; mat[12] = tmp12; mat[13] = tmp13; mat[14] = tmp14; mat[15] = tmp15; updateState(); return this; } /** * Sets this transform to the identity matrix. * * @return this transform */ public GeneralTransform3D setIdentity() { mat[0] = 1.0; mat[1] = 0.0; mat[2] = 0.0; mat[3] = 0.0; mat[4] = 0.0; mat[5] = 1.0; mat[6] = 0.0; mat[7] = 0.0; mat[8] = 0.0; mat[9] = 0.0; mat[10] = 1.0; mat[11] = 0.0; mat[12] = 0.0; mat[13] = 0.0; mat[14] = 0.0; mat[15] = 1.0; identity = true; return this; } /** * Returns true if the transform is identity. A transform is considered * to be identity if the diagonal elements of its matrix is all 1s * otherwise 0s. */ public boolean isIdentity() { return identity; } private void updateState() { //set the identity flag. identity = mat[0] == 1.0 && mat[5] == 1.0 && mat[10] == 1.0 && mat[15] == 1.0 && mat[1] == 0.0 && mat[2] == 0.0 && mat[3] == 0.0 && mat[4] == 0.0 && mat[6] == 0.0 && mat[7] == 0.0 && mat[8] == 0.0 && mat[9] == 0.0 && mat[11] == 0.0 && mat[12] == 0.0 && mat[13] == 0.0 && mat[14] == 0.0; } // Check whether matrix has an Infinity or NaN value. If so, don't treat it // as affine. boolean isInfOrNaN() { // The following is a faster version of the check. // Instead of 3 tests per array element (Double.isInfinite is 2 tests), // for a total of 48 tests, we will do 16 multiplies and 1 test. double d = 0.0; for (int i = 0; i < mat.length; i++) { d *= mat[i]; } return d != 0.0; } private static final double EPSILON_ABSOLUTE = 1.0e-5; static boolean almostZero(double a) { return ((a < EPSILON_ABSOLUTE) && (a > -EPSILON_ABSOLUTE)); } static boolean almostOne(double a) { return ((a < 1+EPSILON_ABSOLUTE) && (a > 1-EPSILON_ABSOLUTE)); } public GeneralTransform3D copy() { GeneralTransform3D newTransform = new GeneralTransform3D(); newTransform.set(this); return newTransform; } /** * Returns the matrix elements of this transform as a string. * @return the matrix elements of this transform */ @Override public String toString() { return mat[0] + ", " + mat[1] + ", " + mat[2] + ", " + mat[3] + "\n" + mat[4] + ", " + mat[5] + ", " + mat[6] + ", " + mat[7] + "\n" + mat[8] + ", " + mat[9] + ", " + mat[10] + ", " + mat[11] + "\n" + mat[12] + ", " + mat[13] + ", " + mat[14] + ", " + mat[15] + "\n"; } }
Ms-Dos/Windows
Unix
Write backup
jsp File Browser version 1.2 by
www.vonloesch.de