/****************************************************************************+ −
**+ −
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).+ −
** All rights reserved.+ −
** Contact: Nokia Corporation (qt-info@nokia.com)+ −
**+ −
** This file is part of the demonstration applications of the Qt Toolkit.+ −
**+ −
** $QT_BEGIN_LICENSE:LGPL$+ −
** No Commercial Usage+ −
** This file contains pre-release code and may not be distributed.+ −
** You may use this file in accordance with the terms and conditions+ −
** contained in the Technology Preview License Agreement accompanying+ −
** this package.+ −
**+ −
** GNU Lesser General Public License Usage+ −
** Alternatively, this file may be used under the terms of the GNU Lesser+ −
** General Public License version 2.1 as published by the Free Software+ −
** Foundation and appearing in the file LICENSE.LGPL included in the+ −
** packaging of this file. Please review the following information to+ −
** ensure the GNU Lesser General Public License version 2.1 requirements+ −
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.+ −
**+ −
** In addition, as a special exception, Nokia gives you certain additional+ −
** rights. These rights are described in the Nokia Qt LGPL Exception+ −
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.+ −
**+ −
** If you have questions regarding the use of this file, please contact+ −
** Nokia at qt-info@nokia.com.+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
** $QT_END_LICENSE$+ −
**+ −
****************************************************************************/+ −
+ −
#include "trackball.h"+ −
#include "scene.h"+ −
+ −
//============================================================================//+ −
// TrackBall //+ −
//============================================================================//+ −
+ −
TrackBall::TrackBall(TrackMode mode)+ −
: m_angularVelocity(0)+ −
, m_paused(false)+ −
, m_pressed(false)+ −
, m_mode(mode)+ −
{+ −
m_axis = QVector3D(0, 1, 0);+ −
m_rotation = QQuaternion();+ −
m_lastTime = QTime::currentTime();+ −
}+ −
+ −
TrackBall::TrackBall(float angularVelocity, const QVector3D& axis, TrackMode mode)+ −
: m_axis(axis)+ −
, m_angularVelocity(angularVelocity)+ −
, m_paused(false)+ −
, m_pressed(false)+ −
, m_mode(mode)+ −
{+ −
m_rotation = QQuaternion();+ −
m_lastTime = QTime::currentTime();+ −
}+ −
+ −
void TrackBall::push(const QPointF& p, const QQuaternion &)+ −
{+ −
m_rotation = rotation();+ −
m_pressed = true;+ −
m_lastTime = QTime::currentTime();+ −
m_lastPos = p;+ −
m_angularVelocity = 0.0f;+ −
}+ −
+ −
void TrackBall::move(const QPointF& p, const QQuaternion &transformation)+ −
{+ −
if (!m_pressed)+ −
return;+ −
+ −
QTime currentTime = QTime::currentTime();+ −
int msecs = m_lastTime.msecsTo(currentTime);+ −
if (msecs <= 20)+ −
return;+ −
+ −
switch (m_mode) {+ −
case Plane:+ −
{+ −
QLineF delta(m_lastPos, p);+ −
m_angularVelocity = 180*delta.length() / (PI*msecs);+ −
m_axis = QVector3D(-delta.dy(), delta.dx(), 0.0f).normalized();+ −
m_axis = transformation.rotatedVector(m_axis);+ −
m_rotation = QQuaternion::fromAxisAndAngle(m_axis, 180 / PI * delta.length()) * m_rotation;+ −
}+ −
break;+ −
case Sphere:+ −
{+ −
QVector3D lastPos3D = QVector3D(m_lastPos.x(), m_lastPos.y(), 0.0f);+ −
float sqrZ = 1 - QVector3D::dotProduct(lastPos3D, lastPos3D);+ −
if (sqrZ > 0)+ −
lastPos3D.setZ(sqrt(sqrZ));+ −
else+ −
lastPos3D.normalize();+ −
+ −
QVector3D currentPos3D = QVector3D(p.x(), p.y(), 0.0f);+ −
sqrZ = 1 - QVector3D::dotProduct(currentPos3D, currentPos3D);+ −
if (sqrZ > 0)+ −
currentPos3D.setZ(sqrt(sqrZ));+ −
else+ −
currentPos3D.normalize();+ −
+ −
m_axis = QVector3D::crossProduct(lastPos3D, currentPos3D);+ −
float angle = 180 / PI * asin(sqrt(QVector3D::dotProduct(m_axis, m_axis)));+ −
+ −
m_angularVelocity = angle / msecs;+ −
m_axis.normalize();+ −
m_axis = transformation.rotatedVector(m_axis);+ −
m_rotation = QQuaternion::fromAxisAndAngle(m_axis, angle) * m_rotation;+ −
}+ −
break;+ −
}+ −
+ −
+ −
m_lastPos = p;+ −
m_lastTime = currentTime;+ −
}+ −
+ −
void TrackBall::release(const QPointF& p, const QQuaternion &transformation)+ −
{+ −
// Calling move() caused the rotation to stop if the framerate was too low.+ −
move(p, transformation);+ −
m_pressed = false;+ −
}+ −
+ −
void TrackBall::start()+ −
{+ −
m_lastTime = QTime::currentTime();+ −
m_paused = false;+ −
}+ −
+ −
void TrackBall::stop()+ −
{+ −
m_rotation = rotation();+ −
m_paused = true;+ −
}+ −
+ −
QQuaternion TrackBall::rotation() const+ −
{+ −
if (m_paused || m_pressed)+ −
return m_rotation;+ −
+ −
QTime currentTime = QTime::currentTime();+ −
float angle = m_angularVelocity * m_lastTime.msecsTo(currentTime);+ −
return QQuaternion::fromAxisAndAngle(m_axis, angle) * m_rotation;+ −
}+ −
+ −