Transform implements Cloneable, Savable, Externalizable, ReadOnlyTransform, Poolable { @Override public Transform multiply(final ReadOnlyTransform transformBy, final Transform store) { MathUtils.checkArgumentNotNull(transformBy, "transformBy"); Transform result = store; if (result == null) { result = new Transform(); } if (_identity) { return result.set(transformBy); } if (transformBy.isIdentity()) { return result.set(this); } if (_rotationMatrix && transformBy.isRotationMatrix() && _uniformScale) { result._rotationMatrix = true; final Matrix3 newRotation = result._matrix; newRotation.set(_matrix).multiplyLocal(transformBy.getMatrix()); final Vector3 newTranslation = result._translation.set(transformBy.getTranslation()); _matrix.applyPost(newTranslation, newTranslation); newTranslation.multiplyLocal(_scale.getX()); newTranslation.addLocal(_translation); if (transformBy.isUniformScale()) { result.setScale(_scale.getX() * transformBy.getScale().getX()); } else { final Vector3 scale = result._scale.set(transformBy.getScale()); scale.multiplyLocal(_scale.getX()); } result.updateFlags(true); return result; } final ReadOnlyMatrix3 matrixA = isRotationMatrix() ? _matrix.multiplyDiagonalPost(_scale, Matrix3.fetchTempInstance()) : _matrix; final ReadOnlyMatrix3 matrixB = transformBy.isRotationMatrix() ? transformBy.getMatrix().multiplyDiagonalPost(transformBy.getScale(), Matrix3.fetchTempInstance()) : transformBy.getMatrix(); final Matrix3 newMatrix = result._matrix; newMatrix.set(matrixA).multiplyLocal(matrixB); final Vector3 newTranslate = result._translation; matrixA.applyPost(transformBy.getTranslation(), newTranslate).addLocal(getTranslation()); if (isRotationMatrix()) { Matrix3.releaseTempInstance((Matrix3) matrixA); } if (transformBy.isRotationMatrix()) { Matrix3.releaseTempInstance((Matrix3) matrixB); } result._scale.set(1.0, 1.0, 1.0); result.updateFlags(false); return result; } Transform();  Transform(final ReadOnlyTransform source); protected  Transform(final ReadOnlyMatrix3 matrix, final ReadOnlyVector3 scale, final ReadOnlyVector3 translation,
    final boolean identity, final boolean rotationMatrix, final boolean uniformScale); @Override ReadOnlyMatrix3 getMatrix(); @Override ReadOnlyVector3 getTranslation(); @Override ReadOnlyVector3 getScale(); @Override boolean isIdentity(); @Override boolean isRotationMatrix(); @Override boolean isUniformScale(); Transform setIdentity(); Transform setRotation(final ReadOnlyMatrix3 rotation); Transform setRotation(final ReadOnlyQuaternion rotation); Transform setTranslation(final ReadOnlyVector3 translation); Transform setTranslation(final double x, final double y, final double z); Transform setScale(final ReadOnlyVector3 scale); Transform setScale(final double x, final double y, final double z); Transform setScale(final double uniformScale); Transform set(final ReadOnlyTransform source); Transform translate(final double x, final double y, final double z); Transform translate(final ReadOnlyVector3 vec); @Override Vector3 applyForward(final Vector3 point); @Override Vector3 applyForward(final ReadOnlyVector3 point, final Vector3 store); @Override Vector3 applyInverse(final Vector3 point); @Override Vector3 applyInverse(final ReadOnlyVector3 point, final Vector3 store); @Override Vector3 applyForwardVector(final Vector3 vector); @Override Vector3 applyForwardVector(final ReadOnlyVector3 vector, final Vector3 store); @Override Vector3 applyInverseVector(final Vector3 vector); @Override Vector3 applyInverseVector(final ReadOnlyVector3 vector, final Vector3 store); @Override Transform multiply(final ReadOnlyTransform transformBy, final Transform store); @Override Transform invert(final Transform store); @Override Matrix4 getHomogeneousMatrix(final Matrix4 store); @Override void getGLApplyMatrix(final DoubleBuffer store); @Override void getGLApplyMatrix(final FloatBuffer store); Transform fromHomogeneousMatrix(final ReadOnlyMatrix4 matrix); static boolean isValid(final ReadOnlyTransform transform); @Override String toString(); @Override int hashCode(); @Override boolean equals(final Object o); @Override boolean strictEquals(final Object o); @Override Transform clone(); @Override Class<? extends Transform> getClassTag(); @Override void write(final OutputCapsule capsule); @Override void read(final InputCapsule capsule); @Override void readExternal(final ObjectInput in); @Override void writeExternal(final ObjectOutput out); final static Transform fetchTempInstance(); final static void releaseTempInstance(final Transform trans); static final double ALLOWED_DEVIANCE; static final ReadOnlyTransform IDENTITY; }
@Test public void testMultiply() { final Transform trans1 = new Transform(); final Transform trans2 = new Transform(); assertEquals(Transform.IDENTITY, trans1.multiply(trans2, null)); trans1.setTranslation(1, 2, 3); final Transform trans3 = trans1.multiply(trans2, null); assertEquals(trans1, trans3); trans2.setTranslation(-1, -2, -3); trans1.multiply(trans2, trans3); assertEquals(Transform.IDENTITY, trans3); assertTrue(trans3.isRotationMatrix()); assertTrue(trans3.isIdentity()); assertTrue(trans3.isUniformScale()); trans2.setScale(1, 2, 1); trans1.multiply(trans2, trans3); assertEquals(new Transform().setScale(1, 2, 1), trans3); assertTrue(trans3.isRotationMatrix()); assertFalse(trans3.isIdentity()); assertFalse(trans3.isUniformScale()); trans1.setScale(1, 2, 1); trans1.multiply(trans2, trans3); assertEquals(new Transform().setRotation(new Matrix3(1, 0, 0, 0, 4, 0, 0, 0, 1)).setTranslation(0, -2, 0), trans3); assertFalse(trans3.isRotationMatrix()); assertFalse(trans3.isIdentity()); assertFalse(trans3.isUniformScale()); }