LCOV - code coverage report
Current view: top level - core/geom - SPQuaternion.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 29 29 100.0 %
Date: 2024-05-12 00:16:13 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /**
       2             : Copyright 2013 BlackBerry Inc.
       3             : Copyright (c) 2014-2015 Chukong Technologies
       4             : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
       5             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       6             : 
       7             : Licensed under the Apache License, Version 2.0 (the "License");
       8             : you may not use this file except in compliance with the License.
       9             : You may obtain a copy of the License at
      10             : 
      11             : http://www.apache.org/licenses/LICENSE-2.0
      12             : 
      13             : Unless required by applicable law or agreed to in writing, software
      14             : distributed under the License is distributed on an "AS IS" BASIS,
      15             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16             : See the License for the specific language governing permissions and
      17             : limitations under the License.
      18             : 
      19             : Original file from GamePlay3D: http://gameplay3d.org
      20             : 
      21             : This file was modified to fit the cocos2d-x project
      22             : This file was modified for stappler project
      23             : */
      24             : 
      25             : #ifndef STAPPLER_GEOM_SPQUATERNION_H_
      26             : #define STAPPLER_GEOM_SPQUATERNION_H_
      27             : 
      28             : #include "SPVec3.h"
      29             : 
      30             : namespace STAPPLER_VERSIONIZED stappler::geom {
      31             : 
      32             : class Mat4;
      33             : 
      34             : /**
      35             :  * Defines a 4-element quaternion that represents the orientation of an object in space.
      36             :  *
      37             :  * Quaternions are typically used as a replacement for euler angles and rotation matrices
      38             :  * as a way to achieve smooth interpolation and avoid gimbal lock.
      39             :  *
      40             :  * Note that this quaternion class does not automatically keep the quaternion normalized.
      41             :  * Therefore, care must be taken to normalize the quaternion when necessary, by calling
      42             :  * the normalize method.
      43             :  * This class provides three methods for doing quaternion interpolation: lerp, slerp, and squad.
      44             :  *
      45             :  * lerp (linear interpolation): the interpolation curve gives a straight line in quaternion
      46             :  * space. It is simple and fast to compute. The only problem is that it does not provide
      47             :  * constant angular velocity. Note that a constant velocity is not necessarily a requirement
      48             :  * for a curve;
      49             :  * slerp (spherical linear interpolation): the interpolation curve forms a great arc on the
      50             :  * quaternion unit sphere. Slerp provides constant angular velocity;
      51             :  * squad (spherical spline interpolation): interpolating between a series of rotations using
      52             :  * slerp leads to the following problems:
      53             :  * - the curve is not smooth at the control points;
      54             :  * - the angular velocity is not constant;
      55             :  * - the angular velocity is not continuous at the control points.
      56             :  *
      57             :  * Since squad is continuously differentiable, it remedies the first and third problems
      58             :  * mentioned above.
      59             :  * The slerp method provided here is intended for interpolation of principal rotations.
      60             :  * It treats +q and -q as the same principal rotation and is at liberty to use the negative
      61             :  * of either input. The resulting path is always the shorter arc.
      62             :  *
      63             :  * The lerp method provided here interpolates strictly in quaternion space. Note that the
      64             :  * resulting path may pass through the origin if interpolating between a quaternion and its
      65             :  * exact negative.
      66             :  *
      67             :  * As an example, consider the following quaternions:
      68             :  *
      69             :  * q1 = (0.6, 0.8, 0.0, 0.0),
      70             :  * q2 = (0.0, 0.6, 0.8, 0.0),
      71             :  * q3 = (0.6, 0.0, 0.8, 0.0), and
      72             :  * q4 = (-0.8, 0.0, -0.6, 0.0).
      73             :  * For the point p = (1.0, 1.0, 1.0), the following figures show the trajectories of p
      74             :  * using lerp, slerp, and squad.
      75             :  */
      76             : class Quaternion {
      77             : public:
      78             :         static void multiply(const Quaternion& q1, const Quaternion& q2, Quaternion* dst);
      79             :         static void lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
      80             : 
      81             :         /**
      82             :          * Interpolates between two quaternions using spherical linear interpolation.
      83             :          *
      84             :          * Spherical linear interpolation provides smooth transitions between different
      85             :          * orientations and is often useful for animating models or cameras in 3D.
      86             :          *
      87             :          * Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
      88             :          * This method does not automatically normalize the input quaternions, so it is up to the
      89             :          * caller to ensure they call normalize beforehand, if necessary.
      90             :          *
      91             :          * @param q1 The first quaternion.
      92             :          * @param q2 The second quaternion.
      93             :          * @param t The interpolation coefficient.
      94             :          * @param dst A quaternion to store the result in.
      95             :          */
      96             :         static void slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
      97             : 
      98             :         /**
      99             :          * Interpolates over a series of quaternions using spherical spline interpolation.
     100             :          *
     101             :          * Spherical spline interpolation provides smooth transitions between different
     102             :          * orientations and is often useful for animating models or cameras in 3D.
     103             :          *
     104             :          * Note: For accurate interpolation, the input quaternions must be unit.
     105             :          * This method does not automatically normalize the input quaternions,
     106             :          * so it is up to the caller to ensure they call normalize beforehand, if necessary.
     107             :          *
     108             :          * @param q1 The first quaternion.
     109             :          * @param q2 The second quaternion.
     110             :          * @param s1 The first control point.
     111             :          * @param s2 The second control point.
     112             :          * @param t The interpolation coefficient.
     113             :          * @param dst A quaternion to store the result in.
     114             :          */
     115             :         static void squad(const Quaternion& q1, const Quaternion& q2,
     116             :                         const Quaternion& s1,const Quaternion& s2, float t, Quaternion* dst);
     117             : 
     118             :         float x;
     119             :         float y;
     120             :         float z;
     121             :         float w;
     122             : 
     123       86291 :         constexpr Quaternion() : x(0.0f), y(0.0f), z(0.0f), w(1.0f) { }
     124           4 :         constexpr Quaternion(float xx, float yy, float zz, float ww) : x(xx), y(yy), z(zz), w(ww) { }
     125             : 
     126             :         /** Constructs a quaternion equal to the rotational part of the specified matrix */
     127             :         Quaternion(const Mat4& m);
     128             : 
     129        6584 :         constexpr Quaternion(const Vec3 &eulerAngles) {
     130        6584 :                 float halfRadx = eulerAngles.x / 2.f, halfRady = eulerAngles.y, halfRadz = -eulerAngles.z / 2.f;
     131        6584 :                 float coshalfRadx = std::cos(halfRadx), sinhalfRadx = std::sin(halfRadx),
     132        6584 :                                 coshalfRady = std::cos(halfRady), sinhalfRady = std::sin(halfRady),
     133        6584 :                                 coshalfRadz = std::cos(halfRadz), sinhalfRadz = std::sin(halfRadz);
     134             : 
     135        6584 :                 x = sinhalfRadx * coshalfRady * coshalfRadz - coshalfRadx * sinhalfRady * sinhalfRadz;
     136        6584 :                 y = coshalfRadx * sinhalfRady * coshalfRadz + sinhalfRadx * coshalfRady * sinhalfRadz;
     137        6584 :                 z = coshalfRadx * coshalfRady * sinhalfRadz - sinhalfRadx * sinhalfRady * coshalfRadz;
     138        6584 :                 w = coshalfRadx * coshalfRady * coshalfRadz + sinhalfRadx * sinhalfRady * sinhalfRadz;
     139        6584 :         }
     140             : 
     141             :         /** Constructs a quaternion equal to the rotation from the specified axis and angle. */
     142          25 :         constexpr Quaternion(const Vec3& axis, float angle) {
     143          25 :                 float halfAngle = angle * 0.5f;
     144          25 :                 float sinHalfAngle = std::sin(halfAngle);
     145             : 
     146          25 :                 Vec3 normal(axis);
     147          25 :                 normal.normalize();
     148          25 :                 x = normal.x * sinHalfAngle;
     149          25 :                 y = normal.y * sinHalfAngle;
     150          25 :                 z = normal.z * sinHalfAngle;
     151          25 :                 w = std::cos(halfAngle);
     152          25 :         }
     153             : 
     154             :         constexpr Quaternion(const Quaternion& copy) = default;
     155             : 
     156          21 :         constexpr bool operator==(const Quaternion &q) const { return q.x == x && q.y == y && q.z == z && q.w == w; }
     157             :         constexpr bool operator!=(const Quaternion &q) const { return q.x != x || q.y != y || q.z != z || q.w != w; }
     158             : 
     159          21 :         constexpr Vec3 toEulerAngles() const {
     160          21 :                 Vec3 ret;
     161          21 :                 ret.x = atan2f(2.f * (w * x + y * z), 1.f - 2.f * (x * x + y * y));
     162          21 :                 ret.y = asinf(2.f * (w * y - z * x));
     163          21 :                 ret.z = - atanf(2.f * (w * z + x * y) / (1.f - 2.f * (y * y + z * z)));
     164          21 :                 return ret;
     165             :         }
     166             : 
     167             :         constexpr bool isIdentity() const { return x == 0.0f && y == 0.0f && z == 0.0f && w == 1.0f; }
     168             :         constexpr bool isZero() const { return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f; }
     169             :         constexpr void conjugate() { x = -x; y = -y; z = -z; }
     170             : 
     171             :         constexpr Quaternion getConjugated() const {
     172             :                 Quaternion q(*this);
     173             :                 q.conjugate();
     174             :                 return q;
     175             :         }
     176             : 
     177             :         bool inverse();
     178             :         void multiply(const Quaternion& q);
     179             :         void normalize();
     180             : 
     181             :         Quaternion getInversed() const;
     182             :         Quaternion getNormalized() const;
     183             : 
     184             :         float toAxisAngle(Vec3* e) const;
     185             : 
     186             :         const Quaternion operator*(const Quaternion& q) const {
     187             :                 Quaternion result(*this);
     188             :                 result.multiply(q);
     189             :                 return result;
     190             :         }
     191             : 
     192             :         Vec3 operator*(const Vec3& v) const {
     193             :                 Vec3 uv, uuv;
     194             :                 Vec3 qvec(x, y, z);
     195             :                 Vec3::cross(qvec, v, &uv);
     196             :                 Vec3::cross(qvec, uv, &uuv);
     197             : 
     198             :                 uv *= (2.0f * w);
     199             :                 uuv *= 2.0f;
     200             : 
     201             :                 return v + uv + uuv;
     202             :         }
     203             : 
     204             :         Quaternion& operator*=(const Quaternion& q) {
     205             :                 multiply(q);
     206             :                 return *this;
     207             :         }
     208             : 
     209             :         static const Quaternion IDENTITY;
     210             :         static const Quaternion ZERO;
     211             : };
     212             : 
     213             : #ifndef __LCC__
     214             : 
     215             : constexpr const Quaternion Quaternion::IDENTITY(0.0f, 0.0f, 0.0f, 1.0f);
     216             : constexpr const Quaternion Quaternion::ZERO(0.0f, 0.0f, 0.0f, 0.0f);
     217             : 
     218             : #endif
     219             : 
     220             : }
     221             : 
     222             : #endif /* STAPPLER_GEOM_SPQUATERNION_H_ */

Generated by: LCOV version 1.14