You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
479 lines
17 KiB
479 lines
17 KiB
/**
|
|
Copyright 2013 BlackBerry Inc.
|
|
Copyright (c) 2014-2016 Chukong Technologies Inc.
|
|
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
Original file from GamePlay3D: http://gameplay3d.org
|
|
|
|
This file was modified to fit the cocos2d-x project
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "math/Mat4.h"
|
|
#include "math/Vec3.h"
|
|
//#include "Plane.h"
|
|
|
|
/**
|
|
* @addtogroup base
|
|
* @{
|
|
*/
|
|
|
|
NS_CC_MATH_BEGIN
|
|
|
|
class Mat4;
|
|
class Mat3;
|
|
/**
|
|
* Defines a 4-element quaternion that represents the orientation of an object in space.
|
|
*
|
|
* Quaternions are typically used as a replacement for Euler angles and rotation matrices as a way to achieve smooth interpolation and avoid gimbal lock.
|
|
*
|
|
* Note that this quaternion class does not automatically keep the quaternion normalized. Therefore, care must be taken to normalize the quaternion when necessary, by calling the normalize method.
|
|
* This class provides three methods for doing quaternion interpolation: lerp, slerp, and squad.
|
|
*
|
|
* lerp (linear interpolation): the interpolation curve gives a straight line in quaternion space. It is simple and fast to compute. The only problem is that it does not provide constant angular velocity. Note that a constant velocity is not necessarily a requirement for a curve;
|
|
* slerp (spherical linear interpolation): the interpolation curve forms a great arc on the quaternion unit sphere. Slerp provides constant angular velocity;
|
|
* squad (spherical spline interpolation): interpolating between a series of rotations using slerp leads to the following problems:
|
|
* - the curve is not smooth at the control points;
|
|
* - the angular velocity is not constant;
|
|
* - the angular velocity is not continuous at the control points.
|
|
*
|
|
* Since squad is continuously differentiable, it remedies the first and third problems mentioned above.
|
|
* The slerp method provided here is intended for interpolation of principal rotations. It treats +q and -q as the same principal rotation and is at liberty to use the negative of either input. The resulting path is always the shorter arc.
|
|
*
|
|
* The lerp method provided here interpolates strictly in quaternion space. Note that the resulting path may pass through the origin if interpolating between a quaternion and its exact negative.
|
|
*
|
|
* As an example, consider the following quaternions:
|
|
*
|
|
* q1 = (0.6, 0.8, 0.0, 0.0),
|
|
* q2 = (0.0, 0.6, 0.8, 0.0),
|
|
* q3 = (0.6, 0.0, 0.8, 0.0), and
|
|
* q4 = (-0.8, 0.0, -0.6, 0.0).
|
|
* For the point p = (1.0, 1.0, 1.0), the following figures show the trajectories of p using lerp, slerp, and squad.
|
|
*/
|
|
class CC_DLL Quaternion {
|
|
public:
|
|
/**
|
|
* The x-value of the quaternion's vector component.
|
|
*/
|
|
float x{0.0F};
|
|
/**
|
|
* The y-value of the quaternion's vector component.
|
|
*/
|
|
float y{0.0F};
|
|
/**
|
|
* The z-value of the quaternion's vector component.
|
|
*/
|
|
float z{0.0F};
|
|
/**
|
|
* The scalar component of the quaternion.
|
|
*/
|
|
float w{1.0F};
|
|
|
|
/**
|
|
* Constructs a quaternion initialized to (0, 0, 0, 1).
|
|
*/
|
|
Quaternion() = default;
|
|
|
|
/**
|
|
* Constructs a quaternion.
|
|
*
|
|
* @param xx The x component of the quaternion.
|
|
* @param yy The y component of the quaternion.
|
|
* @param zz The z component of the quaternion.
|
|
* @param ww The w component of the quaternion.
|
|
*/
|
|
Quaternion(float xx, float yy, float zz, float ww);
|
|
|
|
/**
|
|
* Constructs a new quaternion from the values in the specified array.
|
|
*
|
|
* @param array The values for the new quaternion.
|
|
*/
|
|
explicit Quaternion(float *array);
|
|
|
|
/**
|
|
* Constructs a quaternion equal to the rotational part of the specified matrix.
|
|
*
|
|
* @param m The matrix.
|
|
*/
|
|
explicit Quaternion(const Mat4 &m);
|
|
|
|
/**
|
|
* Constructs a quaternion equal to the rotation from the specified axis and angle.
|
|
*
|
|
* @param axis A vector describing the axis of rotation.
|
|
* @param angle The angle of rotation (in radians).
|
|
*/
|
|
Quaternion(const Vec3 &axis, float angle);
|
|
|
|
/**
|
|
* Returns the identity quaternion.
|
|
*
|
|
* @return The identity quaternion.
|
|
*/
|
|
static const Quaternion &identity();
|
|
|
|
/**
|
|
* Returns the quaternion with all zeros.
|
|
*
|
|
* @return The quaternion.
|
|
*/
|
|
static const Quaternion &zero();
|
|
|
|
/**
|
|
* Determines if this quaternion is equal to the identity quaternion.
|
|
*
|
|
* @return true if it is the identity quaternion, false otherwise.
|
|
*/
|
|
bool isIdentity() const;
|
|
|
|
/**
|
|
* Determines if this quaternion is all zeros.
|
|
*
|
|
* @return true if this quaternion is all zeros, false otherwise.
|
|
*/
|
|
bool isZero() const;
|
|
|
|
/**
|
|
* Calculates the quaternion with Euler angles, the rotation order is YZX
|
|
*/
|
|
static void fromEuler(float x, float y, float z, Quaternion *dst);
|
|
|
|
/**
|
|
* Converts the quaternion to angles, result angle x, y in the range of [-180, 180], z in the range of [-90, 90] interval, the rotation order is YZX
|
|
*/
|
|
static void toEuler(const Quaternion &q, bool outerZ, Vec3 *out);
|
|
|
|
/**
|
|
* Creates a quaternion equal to the rotational part of the specified matrix
|
|
* and stores the result in dst.
|
|
*
|
|
* @param m The matrix.
|
|
* @param dst A quaternion to store the conjugate in.
|
|
*/
|
|
static void createFromRotationMatrix(const Mat4 &m, Quaternion *dst);
|
|
|
|
/**
|
|
* Creates this quaternion equal to the rotation from the specified axis and angle
|
|
* and stores the result in dst.
|
|
*
|
|
* @param axis A vector describing the axis of rotation.
|
|
* @param angle The angle of rotation (in radians).
|
|
* @param dst A quaternion to store the conjugate in.
|
|
*/
|
|
static void createFromAxisAngle(const Vec3 &axis, float angle, Quaternion *dst);
|
|
|
|
/**
|
|
* @en Calculates the quaternion with given 2D angle (0, 0, z).
|
|
* @zh 根据 2D 角度(0, 0, z)计算四元数
|
|
*
|
|
* @param out Output quaternion
|
|
* @param z Angle to rotate around Z axis in degrees.
|
|
*/
|
|
static void createFromAngleZ(float z, Quaternion *dst);
|
|
|
|
/**
|
|
* Sets this quaternion to the conjugate of itself.
|
|
*/
|
|
void conjugate();
|
|
|
|
/**
|
|
* Gets the conjugate of this quaternion.
|
|
*
|
|
*/
|
|
Quaternion getConjugated() const;
|
|
|
|
/**
|
|
* Sets this quaternion to the inverse of itself.
|
|
*
|
|
* Note that the inverse of a quaternion is equal to its conjugate
|
|
* when the quaternion is unit-length. For this reason, it is more
|
|
* efficient to use the conjugate method directly when you know your
|
|
* quaternion is already unit-length.
|
|
*/
|
|
void inverse();
|
|
|
|
/**
|
|
* Gets the inverse of this quaternion.
|
|
*
|
|
* Note that the inverse of a quaternion is equal to its conjugate
|
|
* when the quaternion is unit-length. For this reason, it is more
|
|
* efficient to use the conjugate method directly when you know your
|
|
* quaternion is already unit-length.
|
|
*/
|
|
Quaternion getInversed() const;
|
|
|
|
/**
|
|
* Multiplies this quaternion by the specified one and stores the result in this quaternion.
|
|
*
|
|
* @param q The quaternion to multiply.
|
|
*/
|
|
void multiply(const Quaternion &q);
|
|
|
|
/**
|
|
* Multiplies the specified quaternions and stores the result in dst.
|
|
*
|
|
* @param q1 The first quaternion.
|
|
* @param q2 The second quaternion.
|
|
* @param dst A quaternion to store the result in.
|
|
*/
|
|
static void multiply(const Quaternion &q1, const Quaternion &q2, Quaternion *dst);
|
|
|
|
/**
|
|
* Normalizes this quaternion to have unit length.
|
|
*
|
|
* If the quaternion already has unit length or if the length
|
|
* of the quaternion is zero, this method does nothing.
|
|
*/
|
|
void normalize();
|
|
|
|
/**
|
|
* Get the normalized quaternion.
|
|
*
|
|
* If the quaternion already has unit length or if the length
|
|
* of the quaternion is zero, this method simply copies
|
|
* this vector.
|
|
*/
|
|
Quaternion getNormalized() const;
|
|
|
|
/**
|
|
* Sets the elements of the quaternion to the specified values.
|
|
*
|
|
* @param xx The new x-value.
|
|
* @param yy The new y-value.
|
|
* @param zz The new z-value.
|
|
* @param ww The new w-value.
|
|
*/
|
|
void set(float xx, float yy, float zz, float ww);
|
|
|
|
/**
|
|
* Sets the elements of the quaternion from the values in the specified array.
|
|
*
|
|
* @param array An array containing the elements of the quaternion in the order x, y, z, w.
|
|
*/
|
|
void set(const float *array);
|
|
|
|
/**
|
|
* Sets the quaternion equal to the rotational part of the specified matrix.
|
|
*
|
|
* @param m The matrix.
|
|
*/
|
|
void set(const Mat4 &m);
|
|
|
|
/**
|
|
* Sets the quaternion equal to the rotation from the specified axis and angle.
|
|
*
|
|
* @param axis The axis of rotation.
|
|
* @param angle The angle of rotation (in radians).
|
|
*/
|
|
void set(const Vec3 &axis, float angle);
|
|
|
|
/**
|
|
* Sets the elements of this quaternion to a copy of the specified quaternion.
|
|
*
|
|
* @param q The quaternion to copy.
|
|
*/
|
|
void set(const Quaternion &q);
|
|
|
|
/**
|
|
* Sets this quaternion to be equal to the identity quaternion.
|
|
*/
|
|
void setIdentity();
|
|
|
|
/**
|
|
* Converts this Quaternion4f to axis-angle notation. The axis is normalized.
|
|
*
|
|
* @param e The Vec3f which stores the axis.
|
|
*
|
|
* @return The angle (in radians).
|
|
*/
|
|
float toAxisAngle(Vec3 *axis) const;
|
|
|
|
/**
|
|
* Interpolates between two quaternions using linear interpolation.
|
|
*
|
|
* The interpolation curve for linear interpolation between
|
|
* quaternions gives a straight line in quaternion space.
|
|
*
|
|
* @param q1 The first quaternion.
|
|
* @param q2 The second quaternion.
|
|
* @param t The interpolation coefficient.
|
|
* @param dst A quaternion to store the result in.
|
|
*/
|
|
static void lerp(const Quaternion &q1, const Quaternion &q2, float t, Quaternion *dst);
|
|
|
|
/**
|
|
* Calculates the quaternion with the three-dimensional transform matrix, considering no scale included in the matrix
|
|
*/
|
|
static void fromMat3(const Mat3 &m, Quaternion *out);
|
|
|
|
/**
|
|
* Calculates the quaternion with the up direction and the direction of the viewport
|
|
*/
|
|
static void fromViewUp(const Vec3 &view, Quaternion *out);
|
|
static void fromViewUp(const Vec3 &view, const Vec3 &up, Quaternion *out);
|
|
|
|
/**
|
|
* Interpolates between two quaternions using spherical linear interpolation.
|
|
*
|
|
* Spherical linear interpolation provides smooth transitions between different
|
|
* orientations and is often useful for animating models or cameras in 3D.
|
|
*
|
|
* Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
|
|
* This method does not automatically normalize the input quaternions, so it is up to the
|
|
* caller to ensure they call normalize beforehand, if necessary.
|
|
*
|
|
* @param q1 The first quaternion.
|
|
* @param q2 The second quaternion.
|
|
* @param t The interpolation coefficient.
|
|
* @param dst A quaternion to store the result in.
|
|
*/
|
|
static void slerp(const Quaternion &a, const Quaternion &b, float t, Quaternion *dst);
|
|
|
|
/**
|
|
* @en Spherical quaternion interpolation with two control points
|
|
*
|
|
* @param out the receiving quaternion
|
|
* @param a the first operand
|
|
* @param b the second operand
|
|
* @param c the third operand
|
|
* @param d the fourth operand
|
|
* @param t interpolation amount, in the range [0-1], between the two inputs
|
|
* @returns out
|
|
*/
|
|
static void sqlerp(const Quaternion &a, const Quaternion &b, const Quaternion &c, const Quaternion &d, float t, Quaternion *dst);
|
|
|
|
/**
|
|
* Interpolates over a series of quaternions using spherical spline interpolation.
|
|
*
|
|
* Spherical spline interpolation provides smooth transitions between different
|
|
* orientations and is often useful for animating models or cameras in 3D.
|
|
*
|
|
* Note: For accurate interpolation, the input quaternions must be unit.
|
|
* This method does not automatically normalize the input quaternions,
|
|
* so it is up to the caller to ensure they call normalize beforehand, if necessary.
|
|
*
|
|
* @param q1 The first quaternion.
|
|
* @param q2 The second quaternion.
|
|
* @param s1 The first control point.
|
|
* @param s2 The second control point.
|
|
* @param t The interpolation coefficient.
|
|
* @param dst A quaternion to store the result in.
|
|
*/
|
|
/**
|
|
* @deprecated since v3.8.0 please use [[sqlerp]] instead
|
|
*/
|
|
static void squad(const Quaternion &q1, const Quaternion &q2, const Quaternion &s1, const Quaternion &s2, float t, Quaternion *dst);
|
|
|
|
/**
|
|
* @en Quaternion dot product (scalar product)
|
|
* @zh 四元数点积(数量积)
|
|
* @param a The first unit quaternion
|
|
* @param b The second unit quaternion
|
|
*/
|
|
static inline float dot(const Quaternion &a, const Quaternion &b) {
|
|
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
|
}
|
|
|
|
/**
|
|
* @en Gets the angular distance between two unit quaternions
|
|
* @zh 获取两个单位四元数的夹角
|
|
* @param a The first unit quaternion
|
|
* @param b The second unit quaternion
|
|
* @returns Angle between the two quaternions in radians
|
|
*/
|
|
static float angle(const Quaternion &a, const Quaternion &b);
|
|
|
|
/**
|
|
* @en Rotate a `from` unit quaternion towards `to` unit quaternion
|
|
* @zh 将一个起始单位四元数旋转到一个目标单位四元数
|
|
* @param from The first unit quaternion
|
|
* @param to The second unit quaternion
|
|
* @param maxStep The maximum angle of rotation in degrees
|
|
* @returns new unit quaternion generated during rotation
|
|
*/
|
|
static void rotateTowards(const Quaternion &from, const Quaternion &to, float maxStep, Quaternion *dst);
|
|
|
|
/**
|
|
* Calculates the quaternion product of this quaternion with the given quaternion.
|
|
*
|
|
* Note: this does not modify this quaternion.
|
|
*
|
|
* @param q The quaternion to multiply.
|
|
* @return The quaternion product.
|
|
*/
|
|
inline const Quaternion operator*(const Quaternion &q) const;
|
|
|
|
/**
|
|
* Multiplies this quaternion with the given quaternion.
|
|
*
|
|
* @param q The quaternion to multiply.
|
|
* @return This quaternion, after the multiplication occurs.
|
|
*/
|
|
inline Quaternion &operator*=(const Quaternion &q);
|
|
|
|
/**
|
|
* Determines if this quaternion is approximately equal to the given quaternion.
|
|
*/
|
|
inline bool approxEquals(const Quaternion &v, float precision = CC_FLOAT_CMP_PRECISION) const {
|
|
return math::isEqualF(x, v.x, precision) && math::isEqualF(y, v.y, precision) && math::isEqualF(z, v.z, precision) && math::isEqualF(w, v.w, precision);
|
|
}
|
|
|
|
/** equals to Quaternion(0,0,0, 0) */
|
|
static const Quaternion ZERO;
|
|
|
|
private:
|
|
/**
|
|
* Interpolates between two quaternions using spherical linear interpolation.
|
|
*
|
|
* Spherical linear interpolation provides smooth transitions between different
|
|
* orientations and is often useful for animating models or cameras in 3D.
|
|
*
|
|
* Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
|
|
* This method does not automatically normalize the input quaternions, so it is up to the
|
|
* caller to ensure they call normalize beforehand, if necessary.
|
|
*
|
|
* @param q1x The x component of the first quaternion.
|
|
* @param q1y The y component of the first quaternion.
|
|
* @param q1z The z component of the first quaternion.
|
|
* @param q1w The w component of the first quaternion.
|
|
* @param q2x The x component of the second quaternion.
|
|
* @param q2y The y component of the second quaternion.
|
|
* @param q2z The z component of the second quaternion.
|
|
* @param q2w The w component of the second quaternion.
|
|
* @param t The interpolation coefficient.
|
|
* @param dstx A pointer to store the x component of the slerp in.
|
|
* @param dsty A pointer to store the y component of the slerp in.
|
|
* @param dstz A pointer to store the z component of the slerp in.
|
|
* @param dstw A pointer to store the w component of the slerp in.
|
|
*/
|
|
/**
|
|
* @deprecated since v3.8.0
|
|
*/
|
|
static void slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float *dstx, float *dsty, float *dstz, float *dstw);
|
|
|
|
/**
|
|
* @deprecated since v3.8.0
|
|
*/
|
|
static void slerpForSquad(const Quaternion &q1, const Quaternion &q2, float t, Quaternion *dst);
|
|
};
|
|
|
|
NS_CC_MATH_END
|
|
/**
|
|
end of base group
|
|
@}
|
|
*/
|
|
#include "math/Quaternion.inl"
|
|
|