/** * Adds a rotation to this transform. * * <p>Quaternions are objectively better than the Euler angles preferred by * Minecraft. This is the preferred method when dealing with rotation * additions. This is for compatibility with the flow-math library.</p> * * <p>Returns the results as a new copy.</p> * * @param rotation The rotation to add * @return A new transform */ public Transform<E> addRotation(Quaterniond rotation) { checkNotNull(rotation, "rotation"); return new Transform<>(getExtent(), getPosition(), toAxesAngles(rotation.mul(getRotationAsQuaternion())), getScale()); }
/** * "Adds" another transform to this one. This is equivalent to adding the * translation, rotation and scale individually. * * <p>Returns the results as a new copy.</p> * * @param other The transform to add * @return A new transform */ public Transform<E> add(Transform<E> other) { checkNotNull(other, "other"); return new Transform<>( getExtent(), getPosition().add(other.getPosition()), toAxesAngles(other.getRotationAsQuaternion().mul(getRotationAsQuaternion())), getScale().mul(other.getScale()) ); }
@Test public void testRotation() { final Vector3d rotation1 = new Vector3d(20, 40, 60); final Quaterniond rotationQuat1 = Quaterniond.fromAxesAnglesDeg(rotation1.getX(), -rotation1.getY(), rotation1.getZ()); final Vector3d rotation2 = new Vector3d(45, 135, 225); final Quaterniond rotationQuat2 = Quaterniond.fromAxesAnglesDeg(rotation2.getX(), -rotation2.getY(), rotation2.getZ()); final Quaterniond rotationQuat1Plus2 = rotationQuat2.mul(rotationQuat1); final Vector3d axesAnglesDeg = rotationQuat1Plus2.getAxesAnglesDeg(); final Vector3d rotation1Plus2 = new Vector3d(axesAnglesDeg.getX(), -axesAnglesDeg.getY(), axesAnglesDeg.getZ()); Transform<Extent> transform = new Transform<>(this.mockExtent1, Vector3d.ZERO, rotation1); assertEquals(rotation1, transform.getRotation()); assertEquals(rotationQuat1, transform.getRotationAsQuaternion()); Assert.assertEquals(rotation1.getX(), transform.getPitch(), EPSILON); Assert.assertEquals(rotation1.getY(), transform.getYaw(), EPSILON); Assert.assertEquals(rotation1.getZ(), transform.getRoll(), EPSILON); transform = transform.addRotation(rotation2); assertEquals(rotationQuat1Plus2, transform.getRotationAsQuaternion()); assertEquals(rotation1Plus2, transform.getRotation()); }
/** * Multiplies the components of this quaternion by a float scalar. * * @param a The multiplication scalar * @return A new quaternion, which has each component multiplied by the scalar */ public Quaterniond mul(float a) { return mul((double) a); }
/** * Multiplies another quaternion with this one. * * @param q The quaternion to multiply with * @return A new quaternion, which is the product of both */ public Quaterniond mul(Quaterniond q) { return mul(q.x, q.y, q.z, q.w); }
/** * Multiplies the float components of another quaternion with this one. * * @param x The x (imaginary) component of the quaternion to multiply with * @param y The y (imaginary) component of the quaternion to multiply with * @param z The z (imaginary) component of the quaternion to multiply with * @param w The w (real) component of the quaternion to multiply with * @return A new quaternion, which is the product of both */ public Quaterniond mul(float x, float y, float z, float w) { return mul((double) x, (double) y, (double) z, (double) w); }
/** * Multiplies another quaternion with this one. * * @param q The quaternion to multiply with * @return A new quaternion, which is the product of both */ public Quaterniond mul(Quaterniond q) { return mul(q.x, q.y, q.z, q.w); }
/** * Multiplies the components of this quaternion by a float scalar. * * @param a The multiplication scalar * @return A new quaternion, which has each component multiplied by the scalar */ public Quaterniond mul(float a) { return mul((double) a); }
/** * Multiplies the float components of another quaternion with this one. * * @param x The x (imaginary) component of the quaternion to multiply with * @param y The y (imaginary) component of the quaternion to multiply with * @param z The z (imaginary) component of the quaternion to multiply with * @param w The w (real) component of the quaternion to multiply with * @return A new quaternion, which is the product of both */ public Quaterniond mul(float x, float y, float z, float w) { return mul((double) x, (double) y, (double) z, (double) w); }
/** * Interpolates a quaternion between two others using linear interpolation. * * @param a The first quaternion * @param b The second quaternion * @param percent The percent for the interpolation, between 0 and 1 inclusively * @return The interpolated quaternion */ public static Quaterniond lerp(Quaterniond a, Quaterniond b, double percent) { return a.mul(1 - percent).add(b.mul(percent)); }
/** * Interpolates a quaternion between two others using linear interpolation. * * @param a The first quaternion * @param b The second quaternion * @param percent The percent for the interpolation, between 0 and 1 inclusively * @return The interpolated quaternion */ public static Quaterniond lerp(Quaterniond a, Quaterniond b, double percent) { return a.mul(1 - percent).add(b.mul(percent)); }
/** * Creates a new quaternion from the double angles in degrees around the x, y and z axes. * * @param pitch The rotation around x * @param yaw The rotation around y * @param roll The rotation around z * @return The quaternion defined by the rotations around the axes */ public static Quaterniond fromAxesAnglesDeg(double pitch, double yaw, double roll) { return Quaterniond.fromAngleDegAxis(yaw, Vector3d.UNIT_Y). mul(Quaterniond.fromAngleDegAxis(pitch, Vector3d.UNIT_X)). mul(Quaterniond.fromAngleDegAxis(roll, Vector3d.UNIT_Z)); }
/** * Creates a new quaternion from the double angles in radians around the x, y and z axes. * * @param pitch The rotation around x * @param yaw The rotation around y * @param roll The rotation around z * @return The quaternion defined by the rotations around the axes */ public static Quaterniond fromAxesAnglesRad(double pitch, double yaw, double roll) { return Quaterniond.fromAngleRadAxis(yaw, Vector3d.UNIT_Y). mul(Quaterniond.fromAngleRadAxis(pitch, Vector3d.UNIT_X)). mul(Quaterniond.fromAngleRadAxis(roll, Vector3d.UNIT_Z)); }
/** * Creates a new quaternion from the double angles in degrees around the x, y and z axes. * * @param pitch The rotation around x * @param yaw The rotation around y * @param roll The rotation around z * @return The quaternion defined by the rotations around the axes */ public static Quaterniond fromAxesAnglesDeg(double pitch, double yaw, double roll) { return Quaterniond.fromAngleDegAxis(yaw, Vector3d.UNIT_Y). mul(Quaterniond.fromAngleDegAxis(pitch, Vector3d.UNIT_X)). mul(Quaterniond.fromAngleDegAxis(roll, Vector3d.UNIT_Z)); }
/** * Creates a new quaternion from the double angles in radians around the x, y and z axes. * * @param pitch The rotation around x * @param yaw The rotation around y * @param roll The rotation around z * @return The quaternion defined by the rotations around the axes */ public static Quaterniond fromAxesAnglesRad(double pitch, double yaw, double roll) { return Quaterniond.fromAngleRadAxis(yaw, Vector3d.UNIT_Y). mul(Quaterniond.fromAngleRadAxis(pitch, Vector3d.UNIT_X)). mul(Quaterniond.fromAngleRadAxis(roll, Vector3d.UNIT_Z)); }
/** * Interpolates a quaternion between two others using spherical linear interpolation. * * @param a The first quaternion * @param b The second quaternion * @param percent The percent for the interpolation, between 0 and 1 inclusively * @return The interpolated quaternion */ public static Quaterniond slerp(Quaterniond a, Quaterniond b, double percent) { final double inverted; double cosineTheta = a.dot(b); if (cosineTheta < 0) { cosineTheta = -cosineTheta; inverted = -1; } else { inverted = 1; } if (1 - cosineTheta < GenericMath.DBL_EPSILON) { return a.mul(1 - percent).add(b.mul(percent * inverted)); } final double theta = (double) TrigMath.acos(cosineTheta); final double sineTheta = TrigMath.sin(theta); final double coefficient1 = TrigMath.sin((1 - percent) * theta) / sineTheta; final double coefficient2 = TrigMath.sin(percent * theta) / sineTheta * inverted; return a.mul(coefficient1).add(b.mul(coefficient2)); }
/** * Interpolates a quaternion between two others using spherical linear interpolation. * * @param a The first quaternion * @param b The second quaternion * @param percent The percent for the interpolation, between 0 and 1 inclusively * @return The interpolated quaternion */ public static Quaterniond slerp(Quaterniond a, Quaterniond b, double percent) { final double inverted; double cosineTheta = a.dot(b); if (cosineTheta < 0) { cosineTheta = -cosineTheta; inverted = -1; } else { inverted = 1; } if (1 - cosineTheta < GenericMath.DBL_EPSILON) { return a.mul(1 - percent).add(b.mul(percent * inverted)); } final double theta = (double) TrigMath.acos(cosineTheta); final double sineTheta = TrigMath.sin(theta); final double coefficient1 = TrigMath.sin((1 - percent) * theta) / sineTheta; final double coefficient2 = TrigMath.sin(percent * theta) / sineTheta * inverted; return a.mul(coefficient1).add(b.mul(coefficient2)); }
/** * Adds a rotation to this transform. * Quaternions are objectively better than * the Euler angles preferred by Minecraft. * This is the preferred method when * dealing with rotation additions. * This is for compatibility with * the flow-math library. * Returns the results as a new copy. * * @param rotation The rotation to add * @return A new transform */ public Transform<E> addRotation(Quaterniond rotation) { checkNotNull(rotation, "rotation"); return new Transform<>(getExtent(), getPosition(), toAxesAngles(rotation.mul(getRotationAsQuaternion())), getScale()); } /**
/** * "Adds" another transform to this one. * This is equivalent to adding the * translation, rotation and scale * individually. Returns the results * as a new copy. * * @param other The transform to add * @return A new transform */ public Transform<E> add(Transform<E> other) { checkNotNull(other, "other"); return new Transform<>( getExtent(), getPosition().add(other.getPosition()), toAxesAngles(other.getRotationAsQuaternion().mul(getRotationAsQuaternion())), getScale().mul(other.getScale()) ); } /**