/** * Calculates the result of concatenating this Rotation with a given Rotation. * * @param rotation The rotation to be appended to this Rotation. * @return The Rotation resulting from the concatenation of this Rotation and the given Rotation. */ public Rotation append(Rotation rotation) { // multiply this rotation's quaternion with the given rotation's quaternion Quaternion product = this.quaternion.multiply(rotation.getQuaternion()); // create and return new Rotation object using the calculated quaternion return new Rotation(product); }
/** * Rotates this camera by a given amount. If <code>relative</code> is set to <code>true</code> * then the rotation will be performed relative to this camera's current orientation. Otherwise, * the rotation will be performed relative to the world coordinate system. * * <p>If this camera's focus is locked, then only rotation about the z axis (roll) will be * performed. * * @param rotation The amount of rotation to be applied to this camera. * @param relative A boolean flag stating whether the rotation performed should be relative to * this camera's current orientation. */ public void rotate(Rotation rotation, boolean relative) { // store current focus point Vector3D focusPoint = getFocusPoint(); // perform rotation if (relative) super.setOrientation(getOrientation().append(rotation)); else super.setOrientation(rotation.append(getOrientation())); // if focus is locked, look at the point of focus if (focusLocked) lookAt(focusPoint); }
/** * Interpolates between this Rotation and a given Rotation by a given interpolation factor. * * @param rotation The terminal point of interpolation. * @param factor The interpolation factor. This value will be clamped to the range [0.0, 1.0]. */ public Rotation slerp(Rotation rotation, double factor) { // store quaternion components for easy access Quaternion startQuat = this.quaternion; Quaternion endQuat = rotation.getQuaternion(); double x1 = startQuat.getX(); double y1 = startQuat.getY(); double z1 = startQuat.getZ(); double w1 = startQuat.getW(); double x2 = endQuat.getX(); double y2 = endQuat.getY(); double z2 = endQuat.getZ(); double w2 = endQuat.getW(); // calculate angle between start and end double cosHalfTheta = w1 * w2 + x1 * x2 + y1 * y2 + z1 * z2; // if start=end or start=-end, we can return start if (Math.abs(cosHalfTheta) >= 1.0) return this; // calculate temporary values double halfTheta = Math.acos(cosHalfTheta); double sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); // if theta is 180°, then the result is not fully defined // we could rotate around any axis normal to start or end if (Math.abs(sinHalfTheta) < 0.001) { Vector3D v1 = startQuat.vectorComponent(); Vector3D v2 = endQuat.vectorComponent(); Vector3D vect = v1.add(v2).multiply(0.5); double scalar = (w1 + w2) * 0.5; return new Rotation(new Quaternion(vect, scalar)); } double ratioA = Math.sin((1 - factor) * halfTheta) / sinHalfTheta; double ratioB = Math.sin(factor * halfTheta) / sinHalfTheta; // compute and return quaternion Vector3D v1 = startQuat.vectorComponent(); Vector3D v2 = endQuat.vectorComponent(); Vector3D vect = v1.multiply(ratioA).add((v2).multiply(ratioB)); double scalar = (w1 * ratioA) + (w2 * ratioB); return new Rotation(new Quaternion(vect, scalar)); }
/** * Rotates this camera by a given amount around a given point. The rotation will be performed * relative to the world coordinate system. If the <cod>reorient</code> flag is set to <code>true * </code>, then the rotation will be applied as a standard rotational transformation would; * altering this camera's orientation. If set to <code>false</code>, this camera's orientation * will remain unchanged as the rotation is performed. * * <p>Note that the camera will maintain focus if the camera's focus is locked. * * @param rotation The amount of rotation to be applied to this camera. * @param point The point, in the world coordinate system, about which the rotation will occur. * @param reorient A flag stating whether or not to alter this camera's orientation as with the * applied rotation. */ public void rotate(Rotation rotation, Vector3D point, boolean reorient) { // store current focus point Vector3D focusPoint = getFocusPoint(); // find vector between given point and camera, in local coordinates Vector3D vect = getPosition().subtract(point); // move camera to given point super.setPosition(point); // rotate camera for standard rotation if (reorient) super.setOrientation(rotation.append(getOrientation())); // rotate vector vect = vect.rotate(rotation); // move back to proper position super.setPosition(getPosition().add(vect)); // if focus is locked, look at original focus point if (focusLocked) lookAt(focusPoint); }