|
@@ -37,28 +37,15 @@ namespace godot {
|
|
|
|
|
|
real_t Quaternion::angle_to(const Quaternion &p_to) const {
|
|
|
real_t d = dot(p_to);
|
|
|
- return Math::acos(CLAMP(d * d * 2 - 1, -1, 1));
|
|
|
+ // acos does clamping.
|
|
|
+ return Math::acos(d * d * 2 - 1);
|
|
|
}
|
|
|
|
|
|
-// get_euler_xyz returns a vector containing the Euler angles in the format
|
|
|
-// (ax,ay,az), where ax is the angle of rotation around x axis,
|
|
|
-// and similar for other axes.
|
|
|
-// This implementation uses XYZ convention (Z is the first rotation).
|
|
|
-Vector3 Quaternion::get_euler_xyz() const {
|
|
|
- Basis m(*this);
|
|
|
- return m.get_euler(EULER_ORDER_XYZ);
|
|
|
-}
|
|
|
-
|
|
|
-// get_euler_yxz returns a vector containing the Euler angles in the format
|
|
|
-// (ax,ay,az), where ax is the angle of rotation around x axis,
|
|
|
-// and similar for other axes.
|
|
|
-// This implementation uses YXZ convention (Z is the first rotation).
|
|
|
-Vector3 Quaternion::get_euler_yxz() const {
|
|
|
+Vector3 Quaternion::get_euler(EulerOrder p_order) const {
|
|
|
#ifdef MATH_CHECKS
|
|
|
- ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion " + operator String() + " must be normalized.");
|
|
|
#endif
|
|
|
- Basis m(*this);
|
|
|
- return m.get_euler(EULER_ORDER_YXZ);
|
|
|
+ return Basis(*this).get_euler(p_order);
|
|
|
}
|
|
|
|
|
|
void Quaternion::operator*=(const Quaternion &p_q) {
|
|
@@ -103,7 +90,7 @@ bool Quaternion::is_normalized() const {
|
|
|
|
|
|
Quaternion Quaternion::inverse() const {
|
|
|
#ifdef MATH_CHECKS
|
|
|
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion " + operator String() + " must be normalized.");
|
|
|
#endif
|
|
|
return Quaternion(-x, -y, -z, w);
|
|
|
}
|
|
@@ -125,10 +112,10 @@ Quaternion Quaternion::exp() const {
|
|
|
return Quaternion(src_v, theta);
|
|
|
}
|
|
|
|
|
|
-Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const {
|
|
|
+Quaternion Quaternion::slerp(const Quaternion &p_to, real_t p_weight) const {
|
|
|
#ifdef MATH_CHECKS
|
|
|
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
|
|
|
- ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized.");
|
|
|
#endif
|
|
|
Quaternion to1;
|
|
|
real_t omega, cosom, sinom, scale0, scale1;
|
|
@@ -166,10 +153,10 @@ Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) con
|
|
|
scale0 * w + scale1 * to1.w);
|
|
|
}
|
|
|
|
|
|
-Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const {
|
|
|
+Quaternion Quaternion::slerpni(const Quaternion &p_to, real_t p_weight) const {
|
|
|
#ifdef MATH_CHECKS
|
|
|
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
|
|
|
- ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized.");
|
|
|
#endif
|
|
|
const Quaternion &from = *this;
|
|
|
|
|
@@ -190,10 +177,10 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) c
|
|
|
invFactor * from.w + newFactor * p_to.w);
|
|
|
}
|
|
|
|
|
|
-Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
|
|
|
+Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight) const {
|
|
|
#ifdef MATH_CHECKS
|
|
|
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
|
|
|
- ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized.");
|
|
|
#endif
|
|
|
Quaternion from_q = *this;
|
|
|
Quaternion pre_q = p_pre_a;
|
|
@@ -236,15 +223,15 @@ Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const
|
|
|
ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
|
|
|
Quaternion q2 = to_q * ln.exp();
|
|
|
|
|
|
- // To cancel error made by Expmap ambiguity, do blends.
|
|
|
+ // To cancel error made by Expmap ambiguity, do blending.
|
|
|
return q1.slerp(q2, p_weight);
|
|
|
}
|
|
|
|
|
|
-Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight,
|
|
|
- const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const {
|
|
|
+Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight,
|
|
|
+ real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const {
|
|
|
#ifdef MATH_CHECKS
|
|
|
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
|
|
|
- ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
|
|
|
+ ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized.");
|
|
|
#endif
|
|
|
Quaternion from_q = *this;
|
|
|
Quaternion pre_q = p_pre_a;
|
|
@@ -287,7 +274,7 @@ Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b
|
|
|
ln.z = Math::cubic_interpolate_in_time(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
|
|
Quaternion q2 = to_q * ln.exp();
|
|
|
|
|
|
- // To cancel error made by Expmap ambiguity, do blends.
|
|
|
+ // To cancel error made by Expmap ambiguity, do blending.
|
|
|
return q1.slerp(q2, p_weight);
|
|
|
}
|
|
|
|
|
@@ -309,7 +296,7 @@ real_t Quaternion::get_angle() const {
|
|
|
|
|
|
Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
|
|
|
#ifdef MATH_CHECKS
|
|
|
- ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
|
|
|
+ ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized.");
|
|
|
#endif
|
|
|
real_t d = p_axis.length();
|
|
|
if (d == 0) {
|
|
@@ -332,7 +319,7 @@ Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
|
|
|
// (ax, ay, az), where ax is the angle of rotation around x axis,
|
|
|
// and similar for other axes.
|
|
|
// This implementation uses YXZ convention (Z is the first rotation).
|
|
|
-Quaternion::Quaternion(const Vector3 &p_euler) {
|
|
|
+Quaternion Quaternion::from_euler(const Vector3 &p_euler) {
|
|
|
real_t half_a1 = p_euler.y * 0.5f;
|
|
|
real_t half_a2 = p_euler.x * 0.5f;
|
|
|
real_t half_a3 = p_euler.z * 0.5f;
|
|
@@ -348,10 +335,11 @@ Quaternion::Quaternion(const Vector3 &p_euler) {
|
|
|
real_t cos_a3 = Math::cos(half_a3);
|
|
|
real_t sin_a3 = Math::sin(half_a3);
|
|
|
|
|
|
- x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
|
|
|
- y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
|
|
|
- z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3;
|
|
|
- w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
|
|
|
+ return Quaternion(
|
|
|
+ sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3,
|
|
|
+ sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3,
|
|
|
+ -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3,
|
|
|
+ sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
|
|
|
}
|
|
|
|
|
|
} // namespace godot
|