| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the QtGui module of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU Lesser General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | 
| 21 | ** packaging of this file. Please review the following information to | 
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | 
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | 
| 24 | ** | 
| 25 | ** GNU General Public License Usage | 
| 26 | ** Alternatively, this file may be used under the terms of the GNU | 
| 27 | ** General Public License version 2.0 or (at your option) the GNU General | 
| 28 | ** Public license version 3 or any later version approved by the KDE Free | 
| 29 | ** Qt Foundation. The licenses are as published by the Free Software | 
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | 
| 31 | ** included in the packaging of this file. Please review the following | 
| 32 | ** information to ensure the GNU General Public License requirements will | 
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | 
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | 
| 35 | ** | 
| 36 | ** $QT_END_LICENSE$ | 
| 37 | ** | 
| 38 | ****************************************************************************/ | 
| 39 |  | 
| 40 | #ifndef QQUATERNION_H | 
| 41 | #define QQUATERNION_H | 
| 42 |  | 
| 43 | #include <QtGui/qtguiglobal.h> | 
| 44 | #include <QtGui/qgenericmatrix.h> | 
| 45 | #include <QtGui/qvector3d.h> | 
| 46 | #include <QtGui/qvector4d.h> | 
| 47 |  | 
| 48 | QT_BEGIN_NAMESPACE | 
| 49 |  | 
| 50 |  | 
| 51 | #ifndef QT_NO_QUATERNION | 
| 52 |  | 
| 53 | class QMatrix4x4; | 
| 54 | class QVariant; | 
| 55 |  | 
| 56 | class Q_GUI_EXPORT QQuaternion | 
| 57 | { | 
| 58 | public: | 
| 59 |     QQuaternion(); | 
| 60 |     explicit QQuaternion(Qt::Initialization) {} | 
| 61 |     QQuaternion(float scalar, float xpos, float ypos, float zpos); | 
| 62 | #ifndef QT_NO_VECTOR3D | 
| 63 |     QQuaternion(float scalar, const QVector3D& vector); | 
| 64 | #endif | 
| 65 | #ifndef QT_NO_VECTOR4D | 
| 66 |     explicit QQuaternion(const QVector4D& vector); | 
| 67 | #endif | 
| 68 |  | 
| 69 |     bool isNull() const; | 
| 70 |     bool isIdentity() const; | 
| 71 |  | 
| 72 | #ifndef QT_NO_VECTOR3D | 
| 73 |     QVector3D vector() const; | 
| 74 |     void setVector(const QVector3D& vector); | 
| 75 | #endif | 
| 76 |     void setVector(float x, float y, float z); | 
| 77 |  | 
| 78 |     float x() const; | 
| 79 |     float y() const; | 
| 80 |     float z() const; | 
| 81 |     float scalar() const; | 
| 82 |  | 
| 83 |     void setX(float x); | 
| 84 |     void setY(float y); | 
| 85 |     void setZ(float z); | 
| 86 |     void setScalar(float scalar); | 
| 87 |  | 
| 88 |     Q_DECL_CONSTEXPR static inline float dotProduct(const QQuaternion &q1, const QQuaternion &q2); | 
| 89 |  | 
| 90 |     float length() const; | 
| 91 |     float lengthSquared() const; | 
| 92 |  | 
| 93 |     Q_REQUIRED_RESULT QQuaternion normalized() const; | 
| 94 |     void normalize(); | 
| 95 |  | 
| 96 |     inline QQuaternion inverted() const; | 
| 97 |  | 
| 98 |     Q_REQUIRED_RESULT QQuaternion conjugated() const; | 
| 99 | #if QT_DEPRECATED_SINCE(5, 5) | 
| 100 |     Q_REQUIRED_RESULT QT_DEPRECATED QQuaternion conjugate() const; | 
| 101 | #endif | 
| 102 |  | 
| 103 |     QVector3D rotatedVector(const QVector3D& vector) const; | 
| 104 |  | 
| 105 |     QQuaternion &operator+=(const QQuaternion &quaternion); | 
| 106 |     QQuaternion &operator-=(const QQuaternion &quaternion); | 
| 107 |     QQuaternion &operator*=(float factor); | 
| 108 |     QQuaternion &operator*=(const QQuaternion &quaternion); | 
| 109 |     QQuaternion &operator/=(float divisor); | 
| 110 |  | 
| 111 |     friend inline bool operator==(const QQuaternion &q1, const QQuaternion &q2); | 
| 112 |     friend inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2); | 
| 113 |     friend inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2); | 
| 114 |     friend inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2); | 
| 115 |     friend inline const QQuaternion operator*(float factor, const QQuaternion &quaternion); | 
| 116 |     friend inline const QQuaternion operator*(const QQuaternion &quaternion, float factor); | 
| 117 |     friend inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2); | 
| 118 |     friend inline const QQuaternion operator-(const QQuaternion &quaternion); | 
| 119 |     friend inline const QQuaternion operator/(const QQuaternion &quaternion, float divisor); | 
| 120 |  | 
| 121 |     friend inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2); | 
| 122 |  | 
| 123 | #ifndef QT_NO_VECTOR4D | 
| 124 |     QVector4D toVector4D() const; | 
| 125 | #endif | 
| 126 |  | 
| 127 |     operator QVariant() const; | 
| 128 |  | 
| 129 | #ifndef QT_NO_VECTOR3D | 
| 130 |     inline void getAxisAndAngle(QVector3D *axis, float *angle) const; | 
| 131 |     static QQuaternion fromAxisAndAngle(const QVector3D& axis, float angle); | 
| 132 | #endif | 
| 133 |     void getAxisAndAngle(float *x, float *y, float *z, float *angle) const; | 
| 134 |     static QQuaternion fromAxisAndAngle | 
| 135 |             (float x, float y, float z, float angle); | 
| 136 |  | 
| 137 | #ifndef QT_NO_VECTOR3D | 
| 138 |     inline QVector3D toEulerAngles() const; | 
| 139 |     static inline QQuaternion fromEulerAngles(const QVector3D &eulerAngles); | 
| 140 | #endif | 
| 141 |     void getEulerAngles(float *pitch, float *yaw, float *roll) const; | 
| 142 |     static QQuaternion fromEulerAngles(float pitch, float yaw, float roll); | 
| 143 |  | 
| 144 |     QMatrix3x3 toRotationMatrix() const; | 
| 145 |     static QQuaternion fromRotationMatrix(const QMatrix3x3 &rot3x3); | 
| 146 |  | 
| 147 | #ifndef QT_NO_VECTOR3D | 
| 148 |     void getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const; | 
| 149 |     static QQuaternion fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis); | 
| 150 |  | 
| 151 |     static QQuaternion fromDirection(const QVector3D &direction, const QVector3D &up); | 
| 152 |  | 
| 153 |     static QQuaternion rotationTo(const QVector3D &from, const QVector3D &to); | 
| 154 | #endif | 
| 155 |  | 
| 156 |     static QQuaternion slerp | 
| 157 |         (const QQuaternion& q1, const QQuaternion& q2, float t); | 
| 158 |     static QQuaternion nlerp | 
| 159 |         (const QQuaternion& q1, const QQuaternion& q2, float t); | 
| 160 |  | 
| 161 | private: | 
| 162 |     float wp, xp, yp, zp; | 
| 163 | }; | 
| 164 |  | 
| 165 | Q_DECLARE_TYPEINFO(QQuaternion, Q_MOVABLE_TYPE); | 
| 166 |  | 
| 167 | inline QQuaternion::QQuaternion() : wp(1.0f), xp(0.0f), yp(0.0f), zp(0.0f) {} | 
| 168 |  | 
| 169 | inline QQuaternion::QQuaternion(float aScalar, float xpos, float ypos, float zpos) : wp(aScalar), xp(xpos), yp(ypos), zp(zpos) {} | 
| 170 |  | 
| 171 | QT_WARNING_PUSH | 
| 172 | QT_WARNING_DISABLE_CLANG("-Wfloat-equal" ) | 
| 173 | QT_WARNING_DISABLE_GCC("-Wfloat-equal" ) | 
| 174 | QT_WARNING_DISABLE_INTEL(1572) | 
| 175 | inline bool QQuaternion::isNull() const | 
| 176 | { | 
| 177 |     return wp == 0.0f && xp == 0.0f && yp == 0.0f && zp == 0.0f; | 
| 178 | } | 
| 179 |  | 
| 180 | inline bool QQuaternion::isIdentity() const | 
| 181 | { | 
| 182 |     return wp == 1.0f && xp == 0.0f && yp == 0.0f && zp == 0.0f; | 
| 183 | } | 
| 184 |  | 
| 185 | inline bool operator==(const QQuaternion &q1, const QQuaternion &q2) | 
| 186 | { | 
| 187 |     return q1.wp == q2.wp && q1.xp == q2.xp && q1.yp == q2.yp && q1.zp == q2.zp; | 
| 188 | } | 
| 189 | QT_WARNING_POP | 
| 190 |  | 
| 191 | inline float QQuaternion::x() const { return xp; } | 
| 192 | inline float QQuaternion::y() const { return yp; } | 
| 193 | inline float QQuaternion::z() const { return zp; } | 
| 194 | inline float QQuaternion::scalar() const { return wp; } | 
| 195 |  | 
| 196 | inline void QQuaternion::setX(float aX) { xp = aX; } | 
| 197 | inline void QQuaternion::setY(float aY) { yp = aY; } | 
| 198 | inline void QQuaternion::setZ(float aZ) { zp = aZ; } | 
| 199 | inline void QQuaternion::setScalar(float aScalar) { wp = aScalar; } | 
| 200 |  | 
| 201 | Q_DECL_CONSTEXPR inline float QQuaternion::dotProduct(const QQuaternion &q1, const QQuaternion &q2) | 
| 202 | { | 
| 203 |     return q1.wp * q2.wp + q1.xp * q2.xp + q1.yp * q2.yp + q1.zp * q2.zp; | 
| 204 | } | 
| 205 |  | 
| 206 | inline QQuaternion QQuaternion::inverted() const | 
| 207 | { | 
| 208 |     // Need some extra precision if the length is very small. | 
| 209 |     double len = double(wp) * double(wp) + | 
| 210 |                  double(xp) * double(xp) + | 
| 211 |                  double(yp) * double(yp) + | 
| 212 |                  double(zp) * double(zp); | 
| 213 |     if (!qFuzzyIsNull(d: len)) | 
| 214 |         return QQuaternion(float(double(wp) / len), float(double(-xp) / len), | 
| 215 |                            float(double(-yp) / len), float(double(-zp) / len)); | 
| 216 |     return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f); | 
| 217 | } | 
| 218 |  | 
| 219 | inline QQuaternion QQuaternion::conjugated() const | 
| 220 | { | 
| 221 |     return QQuaternion(wp, -xp, -yp, -zp); | 
| 222 | } | 
| 223 |  | 
| 224 | #if QT_DEPRECATED_SINCE(5, 5) | 
| 225 | inline QQuaternion QQuaternion::conjugate() const | 
| 226 | { | 
| 227 |     return conjugated(); | 
| 228 | } | 
| 229 | #endif | 
| 230 |  | 
| 231 | inline QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion) | 
| 232 | { | 
| 233 |     wp += quaternion.wp; | 
| 234 |     xp += quaternion.xp; | 
| 235 |     yp += quaternion.yp; | 
| 236 |     zp += quaternion.zp; | 
| 237 |     return *this; | 
| 238 | } | 
| 239 |  | 
| 240 | inline QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion) | 
| 241 | { | 
| 242 |     wp -= quaternion.wp; | 
| 243 |     xp -= quaternion.xp; | 
| 244 |     yp -= quaternion.yp; | 
| 245 |     zp -= quaternion.zp; | 
| 246 |     return *this; | 
| 247 | } | 
| 248 |  | 
| 249 | inline QQuaternion &QQuaternion::operator*=(float factor) | 
| 250 | { | 
| 251 |     wp *= factor; | 
| 252 |     xp *= factor; | 
| 253 |     yp *= factor; | 
| 254 |     zp *= factor; | 
| 255 |     return *this; | 
| 256 | } | 
| 257 |  | 
| 258 | inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2) | 
| 259 | { | 
| 260 |     float yy = (q1.wp - q1.yp) * (q2.wp + q2.zp); | 
| 261 |     float zz = (q1.wp + q1.yp) * (q2.wp - q2.zp); | 
| 262 |     float ww = (q1.zp + q1.xp) * (q2.xp + q2.yp); | 
| 263 |     float xx = ww + yy + zz; | 
| 264 |     float qq = 0.5f * (xx + (q1.zp - q1.xp) * (q2.xp - q2.yp)); | 
| 265 |  | 
| 266 |     float w = qq - ww + (q1.zp - q1.yp) * (q2.yp - q2.zp); | 
| 267 |     float x = qq - xx + (q1.xp + q1.wp) * (q2.xp + q2.wp); | 
| 268 |     float y = qq - yy + (q1.wp - q1.xp) * (q2.yp + q2.zp); | 
| 269 |     float z = qq - zz + (q1.zp + q1.yp) * (q2.wp - q2.xp); | 
| 270 |  | 
| 271 |     return QQuaternion(w, x, y, z); | 
| 272 | } | 
| 273 |  | 
| 274 | inline QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion) | 
| 275 | { | 
| 276 |     *this = *this * quaternion; | 
| 277 |     return *this; | 
| 278 | } | 
| 279 |  | 
| 280 | inline QQuaternion &QQuaternion::operator/=(float divisor) | 
| 281 | { | 
| 282 |     wp /= divisor; | 
| 283 |     xp /= divisor; | 
| 284 |     yp /= divisor; | 
| 285 |     zp /= divisor; | 
| 286 |     return *this; | 
| 287 | } | 
| 288 |  | 
| 289 | inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2) | 
| 290 | { | 
| 291 |     return !operator==(q1, q2); | 
| 292 | } | 
| 293 |  | 
| 294 | inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2) | 
| 295 | { | 
| 296 |     return QQuaternion(q1.wp + q2.wp, q1.xp + q2.xp, q1.yp + q2.yp, q1.zp + q2.zp); | 
| 297 | } | 
| 298 |  | 
| 299 | inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2) | 
| 300 | { | 
| 301 |     return QQuaternion(q1.wp - q2.wp, q1.xp - q2.xp, q1.yp - q2.yp, q1.zp - q2.zp); | 
| 302 | } | 
| 303 |  | 
| 304 | inline const QQuaternion operator*(float factor, const QQuaternion &quaternion) | 
| 305 | { | 
| 306 |     return QQuaternion(quaternion.wp * factor, quaternion.xp * factor, quaternion.yp * factor, quaternion.zp * factor); | 
| 307 | } | 
| 308 |  | 
| 309 | inline const QQuaternion operator*(const QQuaternion &quaternion, float factor) | 
| 310 | { | 
| 311 |     return QQuaternion(quaternion.wp * factor, quaternion.xp * factor, quaternion.yp * factor, quaternion.zp * factor); | 
| 312 | } | 
| 313 |  | 
| 314 | inline const QQuaternion operator-(const QQuaternion &quaternion) | 
| 315 | { | 
| 316 |     return QQuaternion(-quaternion.wp, -quaternion.xp, -quaternion.yp, -quaternion.zp); | 
| 317 | } | 
| 318 |  | 
| 319 | inline const QQuaternion operator/(const QQuaternion &quaternion, float divisor) | 
| 320 | { | 
| 321 |     return QQuaternion(quaternion.wp / divisor, quaternion.xp / divisor, quaternion.yp / divisor, quaternion.zp / divisor); | 
| 322 | } | 
| 323 |  | 
| 324 | inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2) | 
| 325 | { | 
| 326 |     return qFuzzyCompare(p1: q1.wp, p2: q2.wp) && | 
| 327 |            qFuzzyCompare(p1: q1.xp, p2: q2.xp) && | 
| 328 |            qFuzzyCompare(p1: q1.yp, p2: q2.yp) && | 
| 329 |            qFuzzyCompare(p1: q1.zp, p2: q2.zp); | 
| 330 | } | 
| 331 |  | 
| 332 | #ifndef QT_NO_VECTOR3D | 
| 333 |  | 
| 334 | inline QQuaternion::QQuaternion(float aScalar, const QVector3D& aVector) | 
| 335 |     : wp(aScalar), xp(aVector.x()), yp(aVector.y()), zp(aVector.z()) {} | 
| 336 |  | 
| 337 | inline void QQuaternion::setVector(const QVector3D& aVector) | 
| 338 | { | 
| 339 |     xp = aVector.x(); | 
| 340 |     yp = aVector.y(); | 
| 341 |     zp = aVector.z(); | 
| 342 | } | 
| 343 |  | 
| 344 | inline QVector3D QQuaternion::vector() const | 
| 345 | { | 
| 346 |     return QVector3D(xp, yp, zp); | 
| 347 | } | 
| 348 |  | 
| 349 | inline QVector3D operator*(const QQuaternion &quaternion, const QVector3D &vec) | 
| 350 | { | 
| 351 |     return quaternion.rotatedVector(vector: vec); | 
| 352 | } | 
| 353 |  | 
| 354 | inline void QQuaternion::getAxisAndAngle(QVector3D *axis, float *angle) const | 
| 355 | { | 
| 356 |     float aX, aY, aZ; | 
| 357 |     getAxisAndAngle(x: &aX, y: &aY, z: &aZ, angle); | 
| 358 |     *axis = QVector3D(aX, aY, aZ); | 
| 359 | } | 
| 360 |  | 
| 361 | inline QVector3D QQuaternion::toEulerAngles() const | 
| 362 | { | 
| 363 |     float pitch, yaw, roll; | 
| 364 |     getEulerAngles(pitch: &pitch, yaw: &yaw, roll: &roll); | 
| 365 |     return QVector3D(pitch, yaw, roll); | 
| 366 | } | 
| 367 |  | 
| 368 | inline QQuaternion QQuaternion::fromEulerAngles(const QVector3D &eulerAngles) | 
| 369 | { | 
| 370 |     return QQuaternion::fromEulerAngles(pitch: eulerAngles.x(), yaw: eulerAngles.y(), roll: eulerAngles.z()); | 
| 371 | } | 
| 372 |  | 
| 373 | #endif | 
| 374 |  | 
| 375 | inline void QQuaternion::setVector(float aX, float aY, float aZ) | 
| 376 | { | 
| 377 |     xp = aX; | 
| 378 |     yp = aY; | 
| 379 |     zp = aZ; | 
| 380 | } | 
| 381 |  | 
| 382 | #ifndef QT_NO_VECTOR4D | 
| 383 |  | 
| 384 | inline QQuaternion::QQuaternion(const QVector4D& aVector) | 
| 385 |     : wp(aVector.w()), xp(aVector.x()), yp(aVector.y()), zp(aVector.z()) {} | 
| 386 |  | 
| 387 | inline QVector4D QQuaternion::toVector4D() const | 
| 388 | { | 
| 389 |     return QVector4D(xp, yp, zp, wp); | 
| 390 | } | 
| 391 |  | 
| 392 | #endif | 
| 393 |  | 
| 394 | #ifndef QT_NO_DEBUG_STREAM | 
| 395 | Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QQuaternion &q); | 
| 396 | #endif | 
| 397 |  | 
| 398 | #ifndef QT_NO_DATASTREAM | 
| 399 | Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QQuaternion &); | 
| 400 | Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QQuaternion &); | 
| 401 | #endif | 
| 402 |  | 
| 403 | #endif | 
| 404 |  | 
| 405 | QT_END_NAMESPACE | 
| 406 |  | 
| 407 | #endif | 
| 408 |  |