📄 transform3d.java
字号:
/* * $RCSfile: Transform3D.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Use is subject to license terms. * * $Revision: 1.10 $ * $Date: 2007/04/12 17:34:07 $ * $State: Exp $ */package javax.media.j3d;import javax.vecmath.*;import com.sun.j3d.internal.HashCodeUtil;/** * A generalized transform object represented internally as a 4x4 * double-precision floating point matrix. The mathematical * representation is * row major, as in traditional matrix mathematics. * A Transform3D is used to perform translations, rotations, and * scaling and shear effects.<P> * * A transform has an associated type, and * all type classification is left to the Transform3D object. * A transform will typically have multiple types, unless it is a * general, unclassifiable matrix, in which case it won't be assigned * a type. <P> * * The Transform3D type is internally computed when the transform * object is constructed and updated any time it is modified. A * matrix will typically have multiple types. For example, the type * associated with an identity matrix is the result of ORing all of * the types, except for ZERO and NEGATIVE_DETERMINANT, together. * There are public methods available to get the ORed type of the * transformation, the sign of the determinant, and the least * general matrix type. The matrix type flags are defined as * follows:<P> * <UL> * <LI>ZERO - zero matrix. All of the elements in the matrix * have the value 0.</LI><P> * <LI>IDENTITY - identity matrix. A matrix with ones on its * main diagonal and zeros every where else.</LI><P> * <LI>SCALE - the matrix is a uniform scale matrix - there are * no rotational or translation components.</LI><P> * <LI>ORTHOGONAL - the four row vectors that make up an orthogonal * matrix form a basis, meaning that they are mutually orthogonal. * The scale is unity and there are no translation components.</LI><P> * <LI>RIGID - the upper 3 X 3 of the matrix is orthogonal, and * there is a translation component-the scale is unity.</LI><P> * <LI>CONGRUENT - this is an angle- and length-preserving matrix, * meaning that it can translate, rotate, and reflect about an axis, * and scale by an amount that is uniform in all directions. These * operations preserve the distance between any two points, and the * angle between any two intersecting lines.</LI><P> * <LI>AFFINE - an affine matrix can translate, rotate, reflect, * scale anisotropically, and shear. Lines remain straight, and parallel * lines remain parallel, but the angle between intersecting lines can * change.</LI><P> * </UL> * A matrix is also classified by the sign of its determinant:<P> * <UL> * NEGATIVE_DETERMINANT - this matrix has a negative determinant. * An orthogonal matrix with a positive determinant is a rotation * matrix. An orthogonal matrix with a negative determinant is a * reflection and rotation matrix.<P></UL> * The Java 3D model for 4 X 4 transformations is:<P> * <UL><pre> * [ m00 m01 m02 m03 ] [ x ] [ x' ] * [ m10 m11 m12 m13 ] . [ y ] = [ y' ] * [ m20 m21 m22 m23 ] [ z ] [ z' ] * [ m30 m31 m32 m33 ] [ w ] [ w' ] * * x' = m00 . x+m01 . y+m02 . z+m03 . w * y' = m10 . x+m11 . y+m12 . z+m13 . w * z' = m20 . x+m21 . y+m22 . z+m23 . w * w' = m30 . x+m31 . y+m32 . z+m33 . w * </pre></ul><P> * Note: When transforming a Point3f or a Point3d, the input w is set to * 1. When transforming a Vector3f or Vector3d, the input w is set to 0. */public class Transform3D { double[] mat = new double[16]; //double[] rot = new double[9]; //double[] scales = new double[3]; // allocate the memory only when it is needed. Following three places will allocate the memory, // void setScaleTranslation(), void computeScales() and void computeScaleRotation() double[] rot = null; double[] scales = null; // Unknown until lazy classification is done private int type = 0; // Dirty bit for classification, this is used // for classify() private static final int AFFINE_BIT = 0x01; private static final int ORTHO_BIT = 0x02; private static final int CONGRUENT_BIT = 0x04; private static final int RIGID_BIT = 0x08; private static final int CLASSIFY_BIT = 0x10; // this is used for scales[], rot[] private static final int SCALE_BIT = 0x20; private static final int ROTATION_BIT = 0x40; // set when SVD renormalization is necessary private static final int SVD_BIT = 0x80; private static final int CLASSIFY_ALL_DIRTY = AFFINE_BIT | ORTHO_BIT | CONGRUENT_BIT | RIGID_BIT | CLASSIFY_BIT; private static final int ROTSCALESVD_DIRTY = SCALE_BIT | ROTATION_BIT | SVD_BIT; private static final int ALL_DIRTY = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; private int dirtyBits; boolean autoNormalize = false; // Don't auto normalize by default /* // reused temporaries for compute_svd private boolean svdAllocd =false; private double[] u1 = null; private double[] v1 = null; private double[] t1 = null; // used by both compute_svd and compute_qr private double[] t2 = null; // used by both compute_svd and compute_qr private double[] ts = null; private double[] svdTmp = null; private double[] svdRot = null; private double[] single_values = null; private double[] e = null; private double[] svdScales = null; // from svrReorder private int[] svdOut = null; private double[] svdMag = null; // from compute_qr private double[] cosl = null; private double[] cosr = null; private double[] sinl = null; private double[] sinr = null; private double[] qr_m = null; */ private static final double EPS = 1.110223024E-16; static final double EPSILON = 1.0e-10; static final double EPSILON_ABSOLUTE = 1.0e-5; static final double EPSILON_RELATIVE = 1.0e-4; /** * A zero matrix. */ public static final int ZERO = 0x01; /** * An identity matrix. */ public static final int IDENTITY = 0x02; /** * A Uniform scale matrix with no translation or other * off-diagonal components. */ public static final int SCALE = 0x04; /** * A translation-only matrix with ones on the diagonal. * */ public static final int TRANSLATION = 0x08; /** * The four row vectors that make up an orthogonal matrix form a basis, * meaning that they are mutually orthogonal; an orthogonal matrix with * positive determinant is a pure rotation matrix; a negative * determinant indicates a rotation and a reflection. */ public static final int ORTHOGONAL = 0x10; /** * This matrix is a rotation and a translation with unity scale; * The upper 3x3 of the matrix is orthogonal, and there is a * translation component. */ public static final int RIGID = 0x20; /** * This is an angle and length preserving matrix, meaning that it * can translate, rotate, and reflect * about an axis, and scale by an amount that is uniform in all directions. * These operations preserve the distance between any two points and the * angle between any two intersecting lines. */ public static final int CONGRUENT = 0x40; /** * An affine matrix can translate, rotate, reflect, scale anisotropically, * and shear. Lines remain straight, and parallel lines remain parallel, * but the angle between intersecting lines can change. In order for a * transform to be classified as affine, the 4th row must be: [0, 0, 0, 1]. */ public static final int AFFINE = 0x80; /** * This matrix has a negative determinant; an orthogonal matrix with * a positive determinant is a rotation matrix; an orthogonal matrix * with a negative determinant is a reflection and rotation matrix. */ public static final int NEGATIVE_DETERMINANT = 0x100; /** * The upper 3x3 column vectors that make up an orthogonal * matrix form a basis meaning that they are mutually orthogonal. * It can have non-uniform or zero x/y/z scale as long as * the dot product of any two column is zero. * This one is used by Java3D internal only and should not * expose to the user. */ private static final int ORTHO = 0x40000000; /** * Constructs and initializes a transform from the 4 x 4 matrix. The * type of the constructed transform will be classified automatically. * @param m1 the 4 x 4 transformation matrix */ public Transform3D(Matrix4f m1) { set(m1); } /** * Constructs and initializes a transform from the 4 x 4 matrix. The * type of the constructed transform will be classified automatically. * @param m1 the 4 x 4 transformation matrix */ public Transform3D(Matrix4d m1) { set(m1); } /** * Constructs and initializes a transform from the Transform3D object. * @param t1 the transformation object to be copied */ public Transform3D(Transform3D t1) { set(t1); } /** * Constructs and initializes a transform to the identity matrix. */ public Transform3D() { setIdentity(); // this will also classify the matrix } /** * Constructs and initializes a transform from the float array of * length 16; the top row of the matrix is initialized to the first * four elements of the array, and so on. The type of the transform * object is classified internally. * @param matrix a float array of 16 */ public Transform3D(float[] matrix) { set(matrix); } /** * Constructs and initializes a transform from the double precision array * of length 16; the top row of the matrix is initialized to the first * four elements of the array, and so on. The type of the transform is * classified internally. * @param matrix a float array of 16 */ public Transform3D(double[] matrix) { set(matrix); } /** * Constructs and initializes a transform from the quaternion, * translation, and scale values. The scale is applied only to the * rotational components of the matrix (upper 3 x 3) and not to the * translational components of the matrix. * @param q1 the quaternion value representing the rotational component * @param t1 the translational component of the matrix * @param s the scale value applied to the rotational components */ public Transform3D(Quat4d q1, Vector3d t1, double s) { set(q1, t1, s); } /** * Constructs and initializes a transform from the quaternion, * translation, and scale values. The scale is applied only to the * rotational components of the matrix (upper 3 x 3) and not to the * translational components of the matrix. * @param q1 the quaternion value representing the rotational component * @param t1 the translational component of the matrix * @param s the scale value applied to the rotational components */ public Transform3D(Quat4f q1, Vector3d t1, double s) { set(q1, t1, s); } /** * Constructs and initializes a transform from the quaternion, * translation, and scale values. The scale is applied only to the * rotational components of the matrix (upper 3 x 3) and not to the * translational components of the matrix. * @param q1 the quaternion value representing the rotational component * @param t1 the translational component of the matrix * @param s the scale value applied to the rotational components */ public Transform3D(Quat4f q1, Vector3f t1, float s) { set(q1, t1, s); } /** * Constructs a transform and initializes it to the upper 4 x 4 * of the GMatrix argument. If the parameter matrix is * smaller than 4 x 4, the remaining elements in the transform matrix are * assigned to zero. * @param m1 the GMatrix */ public Transform3D(GMatrix m1) { set(m1); } /** * Constructs and initializes a transform from the rotation matrix, * translation, and scale values. The scale is applied only to the * rotational component of the matrix (upper 3x3) and not to the * translational component of the matrix. * @param m1 the rotation matrix representing the rotational component * @param t1 the translational component of the matrix * @param s the scale value applied to the rotational components */ public Transform3D(Matrix3f m1, Vector3d t1, double s) { set(m1, t1, s); } /** * Constructs and initializes a transform from the rotation matrix, * translation, and scale values. The scale is applied only to the * rotational components of the matrix (upper 3x3) and not to the * translational components of the matrix. * @param m1 the rotation matrix representing the rotational component * @param t1 the translational component of the matrix * @param s the scale value applied to the rotational components */ public Transform3D(Matrix3d m1, Vector3d t1, double s) { set(m1, t1, s); } /** * Constructs and initializes a transform from the rotation matrix, * translation, and scale values. The scale is applied only to the * rotational components of the matrix (upper 3x3) and not to the * translational components of the matrix. * @param m1 the rotation matrix representing the rotational component * @param t1 the translational component of the matrix * @param s the scale value applied to the rotational components */ public Transform3D(Matrix3f m1, Vector3f t1, float s) { set(m1, t1, s); } /** * Returns the type of this matrix as an or'ed bitmask of * of all of the type classifications to which it belongs. * @return or'ed bitmask of all of the type classifications * of this transform */ public final int getType() { if ((dirtyBits & CLASSIFY_BIT) != 0) { classify(); } // clear ORTHO bit which only use internally return (type & ~ORTHO); } // True if type is ORTHO // Since ORTHO didn't take into account the last row. final boolean isOrtho() { if ((dirtyBits & ORTHO_BIT) != 0) { if ((almostZero(mat[0]*mat[2] + mat[4]*mat[6] + mat[8]*mat[10]) && almostZero(mat[0]*mat[1] + mat[4]*mat[5] + mat[8]*mat[9]) && almostZero(mat[1]*mat[2] + mat[5]*mat[6] + mat[9]*mat[10]))) { type |= ORTHO; dirtyBits &= ~ORTHO_BIT; return true; } else { type &= ~ORTHO; dirtyBits &= ~ORTHO_BIT; return false; } } return ((type & ORTHO) != 0); } final boolean isCongruent() { if ((dirtyBits & CONGRUENT_BIT) != 0) { // This will also classify AFFINE classifyRigid(); } return ((type & CONGRUENT) != 0); } final boolean isAffine() { if ((dirtyBits & AFFINE_BIT) != 0) { classifyAffine(); } return ((type & AFFINE) != 0); } final boolean isRigid() { if ((dirtyBits & RIGID_BIT) != 0) { // This will also classify AFFINE & CONGRUENT if ((dirtyBits & CONGRUENT_BIT) != 0) { classifyRigid(); } else { if ((type & CONGRUENT) != 0) { // Matrix is Congruent, need only // to check scale double s; if ((dirtyBits & SCALE_BIT) != 0){ s = mat[0]*mat[0] + mat[4]*mat[4] + mat[8]*mat[8]; // Note that // scales[0] = sqrt(s); // but since sqrt(1) = 1, // we don't need to do s = sqrt(s) here. } else { if(scales == null) scales = new double[3]; s = scales[0]; } if (almostOne(s)) { type |= RIGID; } else { type &= ~RIGID; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -