Line data Source code
1 : // Author(s): Johannes Altmanninger 2 : // Copyright: see the accompanying file COPYING or copy at 3 : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING 4 : // 5 : // Distributed under the Boost Software License, Version 1.0. 6 : // (See accompanying file LICENSE_1_0.txt or copy at 7 : // http://www.boost.org/LICENSE_1_0.txt) 8 : 9 : #include "mcrl2/gui/arcball.h" 10 : 11 : #include "mcrl2/gui/glu.h" 12 : 13 : #ifdef MCRL2_PLATFORM_MAC 14 : #include <GLKit/GLKMatrix4.h> 15 : #endif 16 : 17 : #ifndef M_PI 18 : #define M_PI 3.14159265358979323846264338327950288 19 : #endif 20 : 21 : namespace mcrl2 22 : { 23 : namespace gui 24 : { 25 : 26 : /// \brief Compute the projection of the point p on a sphere that covers the viewport 27 0 : static QVector3D arcballVector(const QPoint& p) 28 : { 29 : float x, y, z; 30 0 : const float radius = 1.5f; 31 : GLint viewport[4]; 32 0 : glGetIntegerv(GL_VIEWPORT, viewport); 33 : 34 : // Compute x and y relative to the middle of the viewport 35 0 : x = (float)p.x() / viewport[2] * 2.0f - 1.0f; 36 0 : y = (float)p.y() / viewport[3] * 2.0f - 1.0f; 37 0 : y = -y; 38 : 39 0 : float squared = x * x + y * y; 40 0 : if (squared <= radius * radius) 41 : { 42 0 : z = std::sqrt(radius * radius - squared); 43 : } 44 : else 45 : { 46 0 : float len = std::sqrt(squared); 47 0 : if (std::isnormal(len)) 48 : { 49 0 : x /= len; 50 0 : y /= len; 51 : } 52 : else 53 : { 54 0 : x = 0.0f; 55 0 : y = 0.0f; 56 : } 57 0 : z = 0.0f; 58 : } 59 0 : return QVector3D(x, y, z).normalized(); 60 : } 61 : 62 0 : QQuaternion arcballRotation(const QPoint& p1, const QPoint& p2) 63 : { 64 : // update rotation based on the difference in mouse coordinates 65 0 : QVector3D v1 = arcballVector(p1).normalized(); 66 0 : QVector3D v2 = arcballVector(p2).normalized(); 67 0 : QVector3D cross = QVector3D::crossProduct(v1, v2); 68 0 : float dot = QVector3D::dotProduct(v1, v2); 69 0 : return QQuaternion(dot, cross); 70 : } 71 : 72 0 : void applyRotation(const QQuaternion& rotation, bool reverse) 73 : { 74 0 : float angle = 180 / M_PI * std::acos(std::min(1.0f, rotation.scalar())); 75 0 : if (reverse) 76 : { 77 0 : angle = -angle; 78 : } 79 : // not sure why the angle has to be doubled 80 0 : glRotatef(2 * angle, rotation.x(), rotation.y(), rotation.z()); 81 0 : } 82 : 83 : } // namespace gui 84 : } // namespace mcrl2