OpenCoverage

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

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