qquaternion.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/math3d/qquaternion.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2015 The Qt Company Ltd.-
4** Contact: http://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL21$-
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 http://www.qt.io/terms-conditions. For further-
15** information use the contact form at http://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 2.1 or version 3 as published by the Free-
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and-
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the-
22** following information to ensure the GNU Lesser General Public License-
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and-
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.-
25**-
26** As a special exception, The Qt Company gives you certain additional-
27** rights. These rights are described in The Qt Company LGPL Exception-
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.-
29**-
30** $QT_END_LICENSE$-
31**-
32****************************************************************************/-
33-
34#include "qquaternion.h"-
35#include <QtCore/qdatastream.h>-
36#include <QtCore/qmath.h>-
37#include <QtCore/qvariant.h>-
38#include <QtCore/qdebug.h>-
39-
40#include <cmath>-
41-
42QT_BEGIN_NAMESPACE-
43-
44#ifndef QT_NO_QUATERNION-
45-
46/*!-
47 \class QQuaternion-
48 \brief The QQuaternion class represents a quaternion consisting of a vector and scalar.-
49 \since 4.6-
50 \ingroup painting-3D-
51 \inmodule QtGui-
52-
53 Quaternions are used to represent rotations in 3D space, and-
54 consist of a 3D rotation axis specified by the x, y, and z-
55 coordinates, and a scalar representing the rotation angle.-
56*/-
57-
58/*!-
59 \fn QQuaternion::QQuaternion()-
60-
61 Constructs an identity quaternion (1, 0, 0, 0), i.e. with the vector (0, 0, 0)-
62 and scalar 1.-
63*/-
64-
65/*!-
66 \fn QQuaternion::QQuaternion(Qt::Initialization)-
67 \since 5.5-
68 \internal-
69-
70 Constructs a quaternion without initializing the contents.-
71*/-
72-
73/*!-
74 \fn QQuaternion::QQuaternion(float scalar, float xpos, float ypos, float zpos)-
75-
76 Constructs a quaternion with the vector (\a xpos, \a ypos, \a zpos)-
77 and \a scalar.-
78*/-
79-
80#ifndef QT_NO_VECTOR3D-
81-
82/*!-
83 \fn QQuaternion::QQuaternion(float scalar, const QVector3D& vector)-
84-
85 Constructs a quaternion vector from the specified \a vector and-
86 \a scalar.-
87-
88 \sa vector(), scalar()-
89*/-
90-
91/*!-
92 \fn QVector3D QQuaternion::vector() const-
93-
94 Returns the vector component of this quaternion.-
95-
96 \sa setVector(), scalar()-
97*/-
98-
99/*!-
100 \fn void QQuaternion::setVector(const QVector3D& vector)-
101-
102 Sets the vector component of this quaternion to \a vector.-
103-
104 \sa vector(), setScalar()-
105*/-
106-
107#endif-
108-
109/*!-
110 \fn void QQuaternion::setVector(float x, float y, float z)-
111-
112 Sets the vector component of this quaternion to (\a x, \a y, \a z).-
113-
114 \sa vector(), setScalar()-
115*/-
116-
117#ifndef QT_NO_VECTOR4D-
118-
119/*!-
120 \fn QQuaternion::QQuaternion(const QVector4D& vector)-
121-
122 Constructs a quaternion from the components of \a vector.-
123*/-
124-
125/*!-
126 \fn QVector4D QQuaternion::toVector4D() const-
127-
128 Returns this quaternion as a 4D vector.-
129*/-
130-
131#endif-
132-
133/*!-
134 \fn bool QQuaternion::isNull() const-
135-
136 Returns \c true if the x, y, z, and scalar components of this-
137 quaternion are set to 0.0; otherwise returns \c false.-
138*/-
139-
140/*!-
141 \fn bool QQuaternion::isIdentity() const-
142-
143 Returns \c true if the x, y, and z components of this-
144 quaternion are set to 0.0, and the scalar component is set-
145 to 1.0; otherwise returns \c false.-
146*/-
147-
148/*!-
149 \fn float QQuaternion::x() const-
150-
151 Returns the x coordinate of this quaternion's vector.-
152-
153 \sa setX(), y(), z(), scalar()-
154*/-
155-
156/*!-
157 \fn float QQuaternion::y() const-
158-
159 Returns the y coordinate of this quaternion's vector.-
160-
161 \sa setY(), x(), z(), scalar()-
162*/-
163-
164/*!-
165 \fn float QQuaternion::z() const-
166-
167 Returns the z coordinate of this quaternion's vector.-
168-
169 \sa setZ(), x(), y(), scalar()-
170*/-
171-
172/*!-
173 \fn float QQuaternion::scalar() const-
174-
175 Returns the scalar component of this quaternion.-
176-
177 \sa setScalar(), x(), y(), z()-
178*/-
179-
180/*!-
181 \fn void QQuaternion::setX(float x)-
182-
183 Sets the x coordinate of this quaternion's vector to the given-
184 \a x coordinate.-
185-
186 \sa x(), setY(), setZ(), setScalar()-
187*/-
188-
189/*!-
190 \fn void QQuaternion::setY(float y)-
191-
192 Sets the y coordinate of this quaternion's vector to the given-
193 \a y coordinate.-
194-
195 \sa y(), setX(), setZ(), setScalar()-
196*/-
197-
198/*!-
199 \fn void QQuaternion::setZ(float z)-
200-
201 Sets the z coordinate of this quaternion's vector to the given-
202 \a z coordinate.-
203-
204 \sa z(), setX(), setY(), setScalar()-
205*/-
206-
207/*!-
208 \fn void QQuaternion::setScalar(float scalar)-
209-
210 Sets the scalar component of this quaternion to \a scalar.-
211-
212 \sa scalar(), setX(), setY(), setZ()-
213*/-
214-
215/*!-
216 \fn float QQuaternion::dotProduct(const QQuaternion &q1, const QQuaternion &q2)-
217 \since 5.5-
218-
219 Returns the dot product of \a q1 and \a q2.-
220-
221 \sa length()-
222*/-
223-
224/*!-
225 Returns the length of the quaternion. This is also called the "norm".-
226-
227 \sa lengthSquared(), normalized(), dotProduct()-
228*/-
229float QQuaternion::length() const-
230{-
231 return std::sqrt(xp * xp + yp * yp + zp * zp + wp * wp);
never executed: return std::sqrt(xp * xp + yp * yp + zp * zp + wp * wp);
0
232}-
233-
234/*!-
235 Returns the squared length of the quaternion.-
236-
237 \sa length(), dotProduct()-
238*/-
239float QQuaternion::lengthSquared() const-
240{-
241 return xp * xp + yp * yp + zp * zp + wp * wp;
never executed: return xp * xp + yp * yp + zp * zp + wp * wp;
0
242}-
243-
244/*!-
245 Returns the normalized unit form of this quaternion.-
246-
247 If this quaternion is null, then a null quaternion is returned.-
248 If the length of the quaternion is very close to 1, then the quaternion-
249 will be returned as-is. Otherwise the normalized form of the-
250 quaternion of length 1 will be returned.-
251-
252 \sa normalize(), length(), dotProduct()-
253*/-
254QQuaternion QQuaternion::normalized() const-
255{-
256 // Need some extra precision if the length is very small.-
257 double len = double(xp) * double(xp) +-
258 double(yp) * double(yp) +-
259 double(zp) * double(zp) +-
260 double(wp) * double(wp);-
261 if (qFuzzyIsNull(len - 1.0f))
qFuzzyIsNull(len - 1.0f)Description
TRUEnever evaluated
FALSEnever evaluated
0
262 return *this;
never executed: return *this;
0
263 else if (!qFuzzyIsNull(len))
!qFuzzyIsNull(len)Description
TRUEnever evaluated
FALSEnever evaluated
0
264 return *this / std::sqrt(len);
never executed: return *this / std::sqrt(len);
0
265 else-
266 return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
never executed: return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
0
267}-
268-
269/*!-
270 Normalizes the current quaternion in place. Nothing happens if this-
271 is a null quaternion or the length of the quaternion is very close to 1.-
272-
273 \sa length(), normalized()-
274*/-
275void QQuaternion::normalize()-
276{-
277 // Need some extra precision if the length is very small.-
278 double len = double(xp) * double(xp) +-
279 double(yp) * double(yp) +-
280 double(zp) * double(zp) +-
281 double(wp) * double(wp);-
282 if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
qFuzzyIsNull(len - 1.0f)Description
TRUEnever evaluated
FALSEnever evaluated
qFuzzyIsNull(len)Description
TRUEnever evaluated
FALSEnever evaluated
0
283 return;
never executed: return;
0
284-
285 len = std::sqrt(len);-
286-
287 xp /= len;-
288 yp /= len;-
289 zp /= len;-
290 wp /= len;-
291}
never executed: end of block
0
292-
293/*!-
294 \fn QQuaternion QQuaternion::inverted() const-
295 \since 5.5-
296-
297 Returns the inverse of this quaternion.-
298 If this quaternion is null, then a null quaternion is returned.-
299-
300 \sa isNull(), length()-
301*/-
302-
303/*!-
304 \fn QQuaternion QQuaternion::conjugated() const-
305 \since 5.5-
306-
307 Returns the conjugate of this quaternion, which is-
308 (-x, -y, -z, scalar).-
309*/-
310-
311/*!-
312 \fn QQuaternion QQuaternion::conjugate() const-
313 \obsolete-
314-
315 Use conjugated() instead.-
316*/-
317-
318/*!-
319 Rotates \a vector with this quaternion to produce a new vector-
320 in 3D space. The following code:-
321-
322 \code-
323 QVector3D result = q.rotatedVector(vector);-
324 \endcode-
325-
326 is equivalent to the following:-
327-
328 \code-
329 QVector3D result = (q * QQuaternion(0, vector) * q.conjugated()).vector();-
330 \endcode-
331*/-
332QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const-
333{-
334 return (*this * QQuaternion(0, vector) * conjugated()).vector();
never executed: return (*this * QQuaternion(0, vector) * conjugated()).vector();
0
335}-
336-
337/*!-
338 \fn QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)-
339-
340 Adds the given \a quaternion to this quaternion and returns a reference to-
341 this quaternion.-
342-
343 \sa operator-=()-
344*/-
345-
346/*!-
347 \fn QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)-
348-
349 Subtracts the given \a quaternion from this quaternion and returns a-
350 reference to this quaternion.-
351-
352 \sa operator+=()-
353*/-
354-
355/*!-
356 \fn QQuaternion &QQuaternion::operator*=(float factor)-
357-
358 Multiplies this quaternion's components by the given \a factor, and-
359 returns a reference to this quaternion.-
360-
361 \sa operator/=()-
362*/-
363-
364/*!-
365 \fn QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion)-
366-
367 Multiplies this quaternion by \a quaternion and returns a reference-
368 to this quaternion.-
369*/-
370-
371/*!-
372 \fn QQuaternion &QQuaternion::operator/=(float divisor)-
373-
374 Divides this quaternion's components by the given \a divisor, and-
375 returns a reference to this quaternion.-
376-
377 \sa operator*=()-
378*/-
379-
380#ifndef QT_NO_VECTOR3D-
381-
382/*!-
383 \fn void QQuaternion::getAxisAndAngle(QVector3D *axis, float *angle) const-
384 \since 5.5-
385 \overload-
386-
387 Extracts a 3D axis \a axis and a rotating angle \a angle (in degrees)-
388 that corresponds to this quaternion.-
389-
390 \sa fromAxisAndAngle()-
391*/-
392-
393/*!-
394 Creates a normalized quaternion that corresponds to rotating through-
395 \a angle degrees about the specified 3D \a axis.-
396-
397 \sa getAxisAndAngle()-
398*/-
399QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, float angle)-
400{-
401 // Algorithm from:-
402 // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56-
403 // We normalize the result just in case the values are close-
404 // to zero, as suggested in the above FAQ.-
405 float a = (angle / 2.0f) * M_PI / 180.0f;-
406 float s = std::sin(a);-
407 float c = std::cos(a);-
408 QVector3D ax = axis.normalized();-
409 return QQuaternion(c, ax.x() * s, ax.y() * s, ax.z() * s).normalized();
never executed: return QQuaternion(c, ax.x() * s, ax.y() * s, ax.z() * s).normalized();
0
410}-
411-
412#endif-
413-
414/*!-
415 \since 5.5-
416-
417 Extracts a 3D axis (\a x, \a y, \a z) and a rotating angle \a angle (in degrees)-
418 that corresponds to this quaternion.-
419-
420 \sa fromAxisAndAngle()-
421*/-
422void QQuaternion::getAxisAndAngle(float *x, float *y, float *z, float *angle) const-
423{-
424 Q_ASSERT(x && y && z && angle);-
425-
426 // The quaternion representing the rotation is-
427 // q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)-
428-
429 float length = xp * xp + yp * yp + zp * zp;-
430 if (!qFuzzyIsNull(length)) {
!qFuzzyIsNull(length)Description
TRUEnever evaluated
FALSEnever evaluated
0
431 *x = xp;-
432 *y = yp;-
433 *z = zp;-
434 if (!qFuzzyIsNull(length - 1.0f)) {
!qFuzzyIsNull(length - 1.0f)Description
TRUEnever evaluated
FALSEnever evaluated
0
435 length = std::sqrt(length);-
436 *x /= length;-
437 *y /= length;-
438 *z /= length;-
439 }
never executed: end of block
0
440 *angle = 2.0f * std::acos(wp);-
441 } else {
never executed: end of block
0
442 // angle is 0 (mod 2*pi), so any axis will fit-
443 *x = *y = *z = *angle = 0.0f;-
444 }
never executed: end of block
0
445-
446 *angle = qRadiansToDegrees(*angle);-
447}
never executed: end of block
0
448-
449/*!-
450 Creates a normalized quaternion that corresponds to rotating through-
451 \a angle degrees about the 3D axis (\a x, \a y, \a z).-
452-
453 \sa getAxisAndAngle()-
454*/-
455QQuaternion QQuaternion::fromAxisAndAngle-
456 (float x, float y, float z, float angle)-
457{-
458 float length = std::sqrt(x * x + y * y + z * z);-
459 if (!qFuzzyIsNull(length - 1.0f) && !qFuzzyIsNull(length)) {
!qFuzzyIsNull(length - 1.0f)Description
TRUEnever evaluated
FALSEnever evaluated
!qFuzzyIsNull(length)Description
TRUEnever evaluated
FALSEnever evaluated
0
460 x /= length;-
461 y /= length;-
462 z /= length;-
463 }
never executed: end of block
0
464 float a = (angle / 2.0f) * M_PI / 180.0f;-
465 float s = std::sin(a);-
466 float c = std::cos(a);-
467 return QQuaternion(c, x * s, y * s, z * s).normalized();
never executed: return QQuaternion(c, x * s, y * s, z * s).normalized();
0
468}-
469-
470#ifndef QT_NO_VECTOR3D-
471-
472/*!-
473 \fn QVector3D QQuaternion::toEulerAngles() const-
474 \since 5.5-
475 \overload-
476-
477 Calculates roll, pitch, and yaw Euler angles (in degrees)-
478 that corresponds to this quaternion.-
479-
480 \sa fromEulerAngles()-
481*/-
482-
483/*!-
484 \fn QQuaternion QQuaternion::fromEulerAngles(const QVector3D &eulerAngles)-
485 \since 5.5-
486 \overload-
487-
488 Creates a quaternion that corresponds to a rotation of \a eulerAngles:-
489 eulerAngles.z() degrees around the z axis, eulerAngles.x() degrees around the x axis,-
490 and eulerAngles.y() degrees around the y axis (in that order).-
491-
492 \sa toEulerAngles()-
493*/-
494-
495#endif // QT_NO_VECTOR3D-
496-
497/*!-
498 \since 5.5-
499-
500 Calculates \a roll, \a pitch, and \a yaw Euler angles (in degrees)-
501 that corresponds to this quaternion.-
502-
503 \sa fromEulerAngles()-
504*/-
505void QQuaternion::getEulerAngles(float *pitch, float *yaw, float *roll) const-
506{-
507 Q_ASSERT(pitch && yaw && roll);-
508-
509 // Algorithm from:-
510 // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q37-
511-
512 float xx = xp * xp;-
513 float xy = xp * yp;-
514 float xz = xp * zp;-
515 float xw = xp * wp;-
516 float yy = yp * yp;-
517 float yz = yp * zp;-
518 float yw = yp * wp;-
519 float zz = zp * zp;-
520 float zw = zp * wp;-
521-
522 const float lengthSquared = xx + yy + zz + wp * wp;-
523 if (!qFuzzyIsNull(lengthSquared - 1.0f) && !qFuzzyIsNull(lengthSquared)) {
!qFuzzyIsNull(...quared - 1.0f)Description
TRUEnever evaluated
FALSEnever evaluated
!qFuzzyIsNull(lengthSquared)Description
TRUEnever evaluated
FALSEnever evaluated
0
524 xx /= lengthSquared;-
525 xy /= lengthSquared; // same as (xp / length) * (yp / length)-
526 xz /= lengthSquared;-
527 xw /= lengthSquared;-
528 yy /= lengthSquared;-
529 yz /= lengthSquared;-
530 yw /= lengthSquared;-
531 zz /= lengthSquared;-
532 zw /= lengthSquared;-
533 }
never executed: end of block
0
534-
535 *pitch = std::asin(-2.0f * (yz - xw));-
536 if (*pitch < M_PI_2) {
*pitch < 1.570...32679489661923Description
TRUEnever evaluated
FALSEnever evaluated
0
537 if (*pitch > -M_PI_2) {
*pitch > -1.57...32679489661923Description
TRUEnever evaluated
FALSEnever evaluated
0
538 *yaw = std::atan2(2.0f * (xz + yw), 1.0f - 2.0f * (xx + yy));-
539 *roll = std::atan2(2.0f * (xy + zw), 1.0f - 2.0f * (xx + zz));-
540 } else {
never executed: end of block
0
541 // not a unique solution-
542 *roll = 0.0f;-
543 *yaw = -std::atan2(-2.0f * (xy - zw), 1.0f - 2.0f * (yy + zz));-
544 }
never executed: end of block
0
545 } else {-
546 // not a unique solution-
547 *roll = 0.0f;-
548 *yaw = std::atan2(-2.0f * (xy - zw), 1.0f - 2.0f * (yy + zz));-
549 }
never executed: end of block
0
550-
551 *pitch = qRadiansToDegrees(*pitch);-
552 *yaw = qRadiansToDegrees(*yaw);-
553 *roll = qRadiansToDegrees(*roll);-
554}
never executed: end of block
0
555-
556/*!-
557 \since 5.5-
558-
559 Creates a quaternion that corresponds to a rotation of-
560 \a roll degrees around the z axis, \a pitch degrees around the x axis,-
561 and \a yaw degrees around the y axis (in that order).-
562-
563 \sa getEulerAngles()-
564*/-
565QQuaternion QQuaternion::fromEulerAngles(float pitch, float yaw, float roll)-
566{-
567 // Algorithm from:-
568 // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60-
569-
570 pitch = qDegreesToRadians(pitch);-
571 yaw = qDegreesToRadians(yaw);-
572 roll = qDegreesToRadians(roll);-
573-
574 pitch *= 0.5f;-
575 yaw *= 0.5f;-
576 roll *= 0.5f;-
577-
578 const float c1 = std::cos(yaw);-
579 const float s1 = std::sin(yaw);-
580 const float c2 = std::cos(roll);-
581 const float s2 = std::sin(roll);-
582 const float c3 = std::cos(pitch);-
583 const float s3 = std::sin(pitch);-
584 const float c1c2 = c1 * c2;-
585 const float s1s2 = s1 * s2;-
586-
587 const float w = c1c2 * c3 + s1s2 * s3;-
588 const float x = c1c2 * s3 + s1s2 * c3;-
589 const float y = s1 * c2 * c3 - c1 * s2 * s3;-
590 const float z = c1 * s2 * c3 - s1 * c2 * s3;-
591-
592 return QQuaternion(w, x, y, z);
never executed: return QQuaternion(w, x, y, z);
0
593}-
594-
595/*!-
596 \since 5.5-
597-
598 Creates a rotation matrix that corresponds to this quaternion.-
599-
600 \note If this quaternion is not normalized,-
601 the resulting rotation matrix will contain scaling information.-
602-
603 \sa fromRotationMatrix(), getAxes()-
604*/-
605QMatrix3x3 QQuaternion::toRotationMatrix() const-
606{-
607 // Algorithm from:-
608 // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54-
609-
610 QMatrix3x3 rot3x3(Qt::Uninitialized);-
611-
612 const float f2x = xp + xp;-
613 const float f2y = yp + yp;-
614 const float f2z = zp + zp;-
615 const float f2xw = f2x * wp;-
616 const float f2yw = f2y * wp;-
617 const float f2zw = f2z * wp;-
618 const float f2xx = f2x * xp;-
619 const float f2xy = f2x * yp;-
620 const float f2xz = f2x * zp;-
621 const float f2yy = f2y * yp;-
622 const float f2yz = f2y * zp;-
623 const float f2zz = f2z * zp;-
624-
625 rot3x3(0, 0) = 1.0f - (f2yy + f2zz);-
626 rot3x3(0, 1) = f2xy - f2zw;-
627 rot3x3(0, 2) = f2xz + f2yw;-
628 rot3x3(1, 0) = f2xy + f2zw;-
629 rot3x3(1, 1) = 1.0f - (f2xx + f2zz);-
630 rot3x3(1, 2) = f2yz - f2xw;-
631 rot3x3(2, 0) = f2xz - f2yw;-
632 rot3x3(2, 1) = f2yz + f2xw;-
633 rot3x3(2, 2) = 1.0f - (f2xx + f2yy);-
634-
635 return rot3x3;
never executed: return rot3x3;
0
636}-
637-
638/*!-
639 \since 5.5-
640-
641 Creates a quaternion that corresponds to a rotation matrix \a rot3x3.-
642-
643 \note If a given rotation matrix is not normalized,-
644 the resulting quaternion will contain scaling information.-
645-
646 \sa toRotationMatrix(), fromAxes()-
647*/-
648QQuaternion QQuaternion::fromRotationMatrix(const QMatrix3x3 &rot3x3)-
649{-
650 // Algorithm from:-
651 // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q55-
652-
653 float scalar;-
654 float axis[3];-
655-
656 const float trace = rot3x3(0, 0) + rot3x3(1, 1) + rot3x3(2, 2);-
657 if (trace > 0.00000001f) {
trace > 0.00000001fDescription
TRUEnever evaluated
FALSEnever evaluated
0
658 const float s = 2.0f * std::sqrt(trace + 1.0f);-
659 scalar = 0.25f * s;-
660 axis[0] = (rot3x3(2, 1) - rot3x3(1, 2)) / s;-
661 axis[1] = (rot3x3(0, 2) - rot3x3(2, 0)) / s;-
662 axis[2] = (rot3x3(1, 0) - rot3x3(0, 1)) / s;-
663 } else {
never executed: end of block
0
664 static int s_next[3] = { 1, 2, 0 };-
665 int i = 0;-
666 if (rot3x3(1, 1) > rot3x3(0, 0))
rot3x3(1, 1) > rot3x3(0, 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
667 i = 1;
never executed: i = 1;
0
668 if (rot3x3(2, 2) > rot3x3(i, i))
rot3x3(2, 2) > rot3x3(i, i)Description
TRUEnever evaluated
FALSEnever evaluated
0
669 i = 2;
never executed: i = 2;
0
670 int j = s_next[i];-
671 int k = s_next[j];-
672-
673 const float s = 2.0f * std::sqrt(rot3x3(i, i) - rot3x3(j, j) - rot3x3(k, k) + 1.0f);-
674 axis[i] = 0.25f * s;-
675 scalar = (rot3x3(k, j) - rot3x3(j, k)) / s;-
676 axis[j] = (rot3x3(j, i) + rot3x3(i, j)) / s;-
677 axis[k] = (rot3x3(k, i) + rot3x3(i, k)) / s;-
678 }
never executed: end of block
0
679-
680 return QQuaternion(scalar, axis[0], axis[1], axis[2]);
never executed: return QQuaternion(scalar, axis[0], axis[1], axis[2]);
0
681}-
682-
683#ifndef QT_NO_VECTOR3D-
684-
685/*!-
686 \since 5.5-
687-
688 Returns the 3 orthonormal axes (\a xAxis, \a yAxis, \a zAxis) defining the quaternion.-
689-
690 \sa fromAxes(), toRotationMatrix()-
691*/-
692void QQuaternion::getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const-
693{-
694 Q_ASSERT(xAxis && yAxis && zAxis);-
695-
696 const QMatrix3x3 rot3x3(toRotationMatrix());-
697-
698 *xAxis = QVector3D(rot3x3(0, 0), rot3x3(1, 0), rot3x3(2, 0));-
699 *yAxis = QVector3D(rot3x3(0, 1), rot3x3(1, 1), rot3x3(2, 1));-
700 *zAxis = QVector3D(rot3x3(0, 2), rot3x3(1, 2), rot3x3(2, 2));-
701}
never executed: end of block
0
702-
703/*!-
704 \since 5.5-
705-
706 Constructs the quaternion using 3 axes (\a xAxis, \a yAxis, \a zAxis).-
707-
708 \note The axes are assumed to be orthonormal.-
709-
710 \sa getAxes(), fromRotationMatrix()-
711*/-
712QQuaternion QQuaternion::fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis)-
713{-
714 QMatrix3x3 rot3x3(Qt::Uninitialized);-
715 rot3x3(0, 0) = xAxis.x();-
716 rot3x3(1, 0) = xAxis.y();-
717 rot3x3(2, 0) = xAxis.z();-
718 rot3x3(0, 1) = yAxis.x();-
719 rot3x3(1, 1) = yAxis.y();-
720 rot3x3(2, 1) = yAxis.z();-
721 rot3x3(0, 2) = zAxis.x();-
722 rot3x3(1, 2) = zAxis.y();-
723 rot3x3(2, 2) = zAxis.z();-
724-
725 return QQuaternion::fromRotationMatrix(rot3x3);
never executed: return QQuaternion::fromRotationMatrix(rot3x3);
0
726}-
727-
728/*!-
729 \since 5.5-
730-
731 Constructs the quaternion using specified forward direction \a direction-
732 and upward direction \a up.-
733 If the upward direction was not specified or the forward and upward-
734 vectors are collinear, a new orthonormal upward direction will be generated.-
735-
736 \sa fromAxes(), rotationTo()-
737*/-
738QQuaternion QQuaternion::fromDirection(const QVector3D &direction, const QVector3D &up)-
739{-
740 if (qFuzzyIsNull(direction.x()) && qFuzzyIsNull(direction.y()) && qFuzzyIsNull(direction.z()))
qFuzzyIsNull(direction.x())Description
TRUEnever evaluated
FALSEnever evaluated
qFuzzyIsNull(direction.y())Description
TRUEnever evaluated
FALSEnever evaluated
qFuzzyIsNull(direction.z())Description
TRUEnever evaluated
FALSEnever evaluated
0
741 return QQuaternion();
never executed: return QQuaternion();
0
742-
743 const QVector3D zAxis(direction.normalized());-
744 QVector3D xAxis(QVector3D::crossProduct(up, zAxis));-
745 if (qFuzzyIsNull(xAxis.lengthSquared())) {
qFuzzyIsNull(x...ngthSquared())Description
TRUEnever evaluated
FALSEnever evaluated
0
746 // collinear or invalid up vector; derive shortest arc to new direction-
747 return QQuaternion::rotationTo(QVector3D(0.0f, 0.0f, 1.0f), zAxis);
never executed: return QQuaternion::rotationTo(QVector3D(0.0f, 0.0f, 1.0f), zAxis);
0
748 }-
749-
750 xAxis.normalize();-
751 const QVector3D yAxis(QVector3D::crossProduct(zAxis, xAxis));-
752-
753 return QQuaternion::fromAxes(xAxis, yAxis, zAxis);
never executed: return QQuaternion::fromAxes(xAxis, yAxis, zAxis);
0
754}-
755-
756/*!-
757 \since 5.5-
758-
759 Returns the shortest arc quaternion to rotate from the direction described by the vector \a from-
760 to the direction described by the vector \a to.-
761-
762 \sa fromDirection()-
763*/-
764QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)-
765{-
766 // Based on Stan Melax's article in Game Programming Gems-
767-
768 const QVector3D v0(from.normalized());-
769 const QVector3D v1(to.normalized());-
770-
771 float d = QVector3D::dotProduct(v0, v1) + 1.0f;-
772-
773 // if dest vector is close to the inverse of source vector, ANY axis of rotation is valid-
774 if (qFuzzyIsNull(d)) {
qFuzzyIsNull(d)Description
TRUEnever evaluated
FALSEnever evaluated
0
775 QVector3D axis = QVector3D::crossProduct(QVector3D(1.0f, 0.0f, 0.0f), v0);-
776 if (qFuzzyIsNull(axis.lengthSquared()))
qFuzzyIsNull(a...ngthSquared())Description
TRUEnever evaluated
FALSEnever evaluated
0
777 axis = QVector3D::crossProduct(QVector3D(0.0f, 1.0f, 0.0f), v0);
never executed: axis = QVector3D::crossProduct(QVector3D(0.0f, 1.0f, 0.0f), v0);
0
778 axis.normalize();-
779-
780 // same as QQuaternion::fromAxisAndAngle(axis, 180.0f)-
781 return QQuaternion(0.0f, axis.x(), axis.y(), axis.z());
never executed: return QQuaternion(0.0f, axis.x(), axis.y(), axis.z());
0
782 }-
783-
784 d = std::sqrt(2.0f * d);-
785 const QVector3D axis(QVector3D::crossProduct(v0, v1) / d);-
786-
787 return QQuaternion(d * 0.5f, axis).normalized();
never executed: return QQuaternion(d * 0.5f, axis).normalized();
0
788}-
789-
790#endif // QT_NO_VECTOR3D-
791-
792/*!-
793 \fn bool operator==(const QQuaternion &q1, const QQuaternion &q2)-
794 \relates QQuaternion-
795-
796 Returns \c true if \a q1 is equal to \a q2; otherwise returns \c false.-
797 This operator uses an exact floating-point comparison.-
798*/-
799-
800/*!-
801 \fn bool operator!=(const QQuaternion &q1, const QQuaternion &q2)-
802 \relates QQuaternion-
803-
804 Returns \c true if \a q1 is not equal to \a q2; otherwise returns \c false.-
805 This operator uses an exact floating-point comparison.-
806*/-
807-
808/*!-
809 \fn const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2)-
810 \relates QQuaternion-
811-
812 Returns a QQuaternion object that is the sum of the given quaternions,-
813 \a q1 and \a q2; each component is added separately.-
814-
815 \sa QQuaternion::operator+=()-
816*/-
817-
818/*!-
819 \fn const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2)-
820 \relates QQuaternion-
821-
822 Returns a QQuaternion object that is formed by subtracting-
823 \a q2 from \a q1; each component is subtracted separately.-
824-
825 \sa QQuaternion::operator-=()-
826*/-
827-
828/*!-
829 \fn const QQuaternion operator*(float factor, const QQuaternion &quaternion)-
830 \relates QQuaternion-
831-
832 Returns a copy of the given \a quaternion, multiplied by the-
833 given \a factor.-
834-
835 \sa QQuaternion::operator*=()-
836*/-
837-
838/*!-
839 \fn const QQuaternion operator*(const QQuaternion &quaternion, float factor)-
840 \relates QQuaternion-
841-
842 Returns a copy of the given \a quaternion, multiplied by the-
843 given \a factor.-
844-
845 \sa QQuaternion::operator*=()-
846*/-
847-
848/*!-
849 \fn const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)-
850 \relates QQuaternion-
851-
852 Multiplies \a q1 and \a q2 using quaternion multiplication.-
853 The result corresponds to applying both of the rotations specified-
854 by \a q1 and \a q2.-
855-
856 \sa QQuaternion::operator*=()-
857*/-
858-
859/*!-
860 \fn const QQuaternion operator-(const QQuaternion &quaternion)-
861 \relates QQuaternion-
862 \overload-
863-
864 Returns a QQuaternion object that is formed by changing the sign of-
865 all three components of the given \a quaternion.-
866-
867 Equivalent to \c {QQuaternion(0,0,0,0) - quaternion}.-
868*/-
869-
870/*!-
871 \fn const QQuaternion operator/(const QQuaternion &quaternion, float divisor)-
872 \relates QQuaternion-
873-
874 Returns the QQuaternion object formed by dividing all components of-
875 the given \a quaternion by the given \a divisor.-
876-
877 \sa QQuaternion::operator/=()-
878*/-
879-
880#ifndef QT_NO_VECTOR3D-
881-
882/*!-
883 \fn QVector3D operator*(const QQuaternion &quaternion, const QVector3D &vec)-
884 \since 5.5-
885 \relates QQuaternion-
886-
887 Rotates a vector \a vec with a quaternion \a quaternion to produce a new vector in 3D space.-
888*/-
889-
890#endif-
891-
892/*!-
893 \fn bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)-
894 \relates QQuaternion-
895-
896 Returns \c true if \a q1 and \a q2 are equal, allowing for a small-
897 fuzziness factor for floating-point comparisons; false otherwise.-
898*/-
899-
900/*!-
901 Interpolates along the shortest spherical path between the-
902 rotational positions \a q1 and \a q2. The value \a t should-
903 be between 0 and 1, indicating the spherical distance to travel-
904 between \a q1 and \a q2.-
905-
906 If \a t is less than or equal to 0, then \a q1 will be returned.-
907 If \a t is greater than or equal to 1, then \a q2 will be returned.-
908-
909 \sa nlerp()-
910*/-
911QQuaternion QQuaternion::slerp-
912 (const QQuaternion& q1, const QQuaternion& q2, float t)-
913{-
914 // Handle the easy cases first.-
915 if (t <= 0.0f)
t <= 0.0fDescription
TRUEnever evaluated
FALSEnever evaluated
0
916 return q1;
never executed: return q1;
0
917 else if (t >= 1.0f)
t >= 1.0fDescription
TRUEnever evaluated
FALSEnever evaluated
0
918 return q2;
never executed: return q2;
0
919-
920 // Determine the angle between the two quaternions.-
921 QQuaternion q2b(q2);-
922 float dot = QQuaternion::dotProduct(q1, q2);-
923 if (dot < 0.0f) {
dot < 0.0fDescription
TRUEnever evaluated
FALSEnever evaluated
0
924 q2b = -q2b;-
925 dot = -dot;-
926 }
never executed: end of block
0
927-
928 // Get the scale factors. If they are too small,-
929 // then revert to simple linear interpolation.-
930 float factor1 = 1.0f - t;-
931 float factor2 = t;-
932 if ((1.0f - dot) > 0.0000001) {
(1.0f - dot) > 0.0000001Description
TRUEnever evaluated
FALSEnever evaluated
0
933 float angle = std::acos(dot);-
934 float sinOfAngle = std::sin(angle);-
935 if (sinOfAngle > 0.0000001) {
sinOfAngle > 0.0000001Description
TRUEnever evaluated
FALSEnever evaluated
0
936 factor1 = std::sin((1.0f - t) * angle) / sinOfAngle;-
937 factor2 = std::sin(t * angle) / sinOfAngle;-
938 }
never executed: end of block
0
939 }
never executed: end of block
0
940-
941 // Construct the result quaternion.-
942 return q1 * factor1 + q2b * factor2;
never executed: return q1 * factor1 + q2b * factor2;
0
943}-
944-
945/*!-
946 Interpolates along the shortest linear path between the rotational-
947 positions \a q1 and \a q2. The value \a t should be between 0 and 1,-
948 indicating the distance to travel between \a q1 and \a q2.-
949 The result will be normalized().-
950-
951 If \a t is less than or equal to 0, then \a q1 will be returned.-
952 If \a t is greater than or equal to 1, then \a q2 will be returned.-
953-
954 The nlerp() function is typically faster than slerp() and will-
955 give approximate results to spherical interpolation that are-
956 good enough for some applications.-
957-
958 \sa slerp()-
959*/-
960QQuaternion QQuaternion::nlerp-
961 (const QQuaternion& q1, const QQuaternion& q2, float t)-
962{-
963 // Handle the easy cases first.-
964 if (t <= 0.0f)
t <= 0.0fDescription
TRUEnever evaluated
FALSEnever evaluated
0
965 return q1;
never executed: return q1;
0
966 else if (t >= 1.0f)
t >= 1.0fDescription
TRUEnever evaluated
FALSEnever evaluated
0
967 return q2;
never executed: return q2;
0
968-
969 // Determine the angle between the two quaternions.-
970 QQuaternion q2b(q2);-
971 float dot = QQuaternion::dotProduct(q1, q2);-
972 if (dot < 0.0f)
dot < 0.0fDescription
TRUEnever evaluated
FALSEnever evaluated
0
973 q2b = -q2b;
never executed: q2b = -q2b;
0
974-
975 // Perform the linear interpolation.-
976 return (q1 * (1.0f - t) + q2b * t).normalized();
never executed: return (q1 * (1.0f - t) + q2b * t).normalized();
0
977}-
978-
979/*!-
980 Returns the quaternion as a QVariant.-
981*/-
982QQuaternion::operator QVariant() const-
983{-
984 return QVariant(QVariant::Quaternion, this);
never executed: return QVariant(QVariant::Quaternion, this);
0
985}-
986-
987#ifndef QT_NO_DEBUG_STREAM-
988-
989QDebug operator<<(QDebug dbg, const QQuaternion &q)-
990{-
991 QDebugStateSaver saver(dbg);-
992 dbg.nospace() << "QQuaternion(scalar:" << q.scalar()-
993 << ", vector:(" << q.x() << ", "-
994 << q.y() << ", " << q.z() << "))";-
995 return dbg;
never executed: return dbg;
0
996}-
997-
998#endif-
999-
1000#ifndef QT_NO_DATASTREAM-
1001-
1002/*!-
1003 \fn QDataStream &operator<<(QDataStream &stream, const QQuaternion &quaternion)-
1004 \relates QQuaternion-
1005-
1006 Writes the given \a quaternion to the given \a stream and returns a-
1007 reference to the stream.-
1008-
1009 \sa {Serializing Qt Data Types}-
1010*/-
1011-
1012QDataStream &operator<<(QDataStream &stream, const QQuaternion &quaternion)-
1013{-
1014 stream << quaternion.scalar() << quaternion.x()-
1015 << quaternion.y() << quaternion.z();-
1016 return stream;
never executed: return stream;
0
1017}-
1018-
1019/*!-
1020 \fn QDataStream &operator>>(QDataStream &stream, QQuaternion &quaternion)-
1021 \relates QQuaternion-
1022-
1023 Reads a quaternion from the given \a stream into the given \a quaternion-
1024 and returns a reference to the stream.-
1025-
1026 \sa {Serializing Qt Data Types}-
1027*/-
1028-
1029QDataStream &operator>>(QDataStream &stream, QQuaternion &quaternion)-
1030{-
1031 float scalar, x, y, z;-
1032 stream >> scalar;-
1033 stream >> x;-
1034 stream >> y;-
1035 stream >> z;-
1036 quaternion.setScalar(scalar);-
1037 quaternion.setX(x);-
1038 quaternion.setY(y);-
1039 quaternion.setZ(z);-
1040 return stream;
never executed: return stream;
0
1041}-
1042-
1043#endif // QT_NO_DATASTREAM-
1044-
1045#endif-
1046-
1047QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9