I am trying to visualize a pointcloud centered around the origin. I also want to have a user controlled rotation for which I found the arcball.
rMat
is the model matrix, passed into the shader.
inline QVector3D getArcballVector(const QPoint& pt, int width, int height)
{
QVector3D P = QVector3D(1.0*pt.x ()/width * 2 - 1.0,
1.0*pt.y ()/height * 2 - 1.0,
0);
P.setY (-P.y ());
float OP_squared = P.lengthSquared ();
if (OP_squared <= 1)
P.setZ (std::sqrt(1 - OP_squared)); // Pythagore
else
P.normalize (); // nearest point
return P;
}
void PointCloud::mouseMoveEvent(QMouseEvent * e)
{
if(e->buttons ()==Qt::LeftButton)
{
if(!rotPos.isNull () && rotPos!=e->pos ())
{
//rotate using an arcBall for freeform rotation
QVector3D vec1 = getArcballVector (rotPos, width (), height ());
QVector3D vec2 = getArcballVector (e->pos (), width (), height ());
//use bisector to get half-angle cos and sin from dot and cross product
// for quaternion initialisation
QVector3D vec3 = vec1+vec2;
vec3.normalize ();
QVector3D rotaxis = QVector3D::crossProduct (vec1, vec3);
double cos = QVector3D::dotProduct (vec1, vec3);
QQuaternion quat (cos,rotaxis);
quat.normalize ();
//we want to left-multiply rMat with quat but that isn't available
//so we'll have to do it the long way around
QMatrix4x4 rot;
rot.rotate (quat);
rMat=rot*rMat;
updateGL ();
}
rotPos=e->pos ();
}
}
void PointCloud::mousePressEvent(QMouseEvent *e)
{
if(e->buttons ()==Qt::LeftButton)
{
rotPos=e->pos ();
}
}
One point to make is that most arcball examples use acos
to get the rotation angle for the axis-angle representation and use that to create the matrix and only mention using quaternions in passing (and if they do use quaternions they still end up using axis-angle). I found that I can derive the quaternion values directly using the dot and cross products of the first vector with the bisector of the 2 vectors (vec3
).
Are there any glaring inefficiencies? I could move the update code to a QTimer activated slot but the usage of the program has the user mostly ignoring the screen while concentrating on the road.