Some times we need to rotate the scene for a better view. Rather than providing separate slider ball control or similar mechanisam to rotate around X,Y,Z axis it is better to do rotation with mouse and it will give a intutive feel to user.
This is not a complex task. With some simple mathematical calculation we can achieve this. A unit Quaternion can represent any arbitary a 3D orientation. Quaternions are nothing but 4Diamensional complex number. Visualizing quaternion is difficult when compared to affine matrices.
Rotation Using Quaternion
When user clicks on the scene we will get the points in window coordinates. we need to convert it into the correct world coordinates. If you are familar with opengl you can use gluUnProject API for this. Otherwise you can simply mul
tiply with corresponding matrices to get this.
So When user dragging the mouse we will get two points in world space ( since dragging is not a continus operation on computer unlike the physical draging process). We can generate a axis from this two points ( vectors ) by taking the cross product between them. The angle of rotation is nothing but arc cosine of dot prodcut of first and second vector.
Now we can create a quaternion which represents the rotation around that axis.
Following code ilustrates this process. I used my Quaternion & vector classes to simplify the process.
Math3D::vector vtFrom;
Math3D::vector vtTo;
gluUnProject(m_PrePoint.x,m_PrePoint.y,0,fModeView,fProjection,iViewPort,&vtFrom.x,&vtFrom.y,&vtFrom.z);
gluUnProject(point.x,point.y,0,fModeView,fProjection,iViewPort,&vtTo.x,&vtTo.y,&vtTo.z);
vtFrom.y = -vtFrom.y;
vtTo.y = -vtTo.y;
vtFrom.normalize();
vtTo.normalize();
Math3D::vector vAxis = vtFrom.Cross( vtTo );
vAxis.normalize();
float fTheta = acos(vtFrom.Dot(vtTo));
Math3D::Quaternion qTmp;
qTmp.FromAxisAngle( vAxis, fTheta *2 );
qTmp.Normalize();
// multiply the current quaternion with the new one.
m_Quat *= qTmp;
m_PrePoint = point;
// normalise it.
m_Quat.Normalize();
Now the scene can be rotated with quaternion m_Quat and the scene will be rotated according the mouse movement made by the user.