class CArcBall
{
protected:
CVector3D start, end; // Start and End vector
float width, height; // Width and Height of the window
void MapToSphere(int x, int y, CVector3D& v)
{
v.x=2*float(x)/width-1;
v.y=-2*float(y)/height+1;
float r2;
r2=v.x*v.x+v.y*v.y;
if(r2>1.0)
{
float r=sqrt(r2);
v.x/=r;
v.y/=r;
v.z=0.0;}
else
{
v.z=sqrt(1.0-r2);
}
}
public:
void SetSize(int width0, int height0)
{width=(float)width0; height=(float)height0;}
void SetStartPoint(int x, int y) { MapToSphere(x, y, start); }
void SetEndPoint(int x, int y) { MapToSphere(x, y, end); }
void GetQuaternion(CQuaternion& quat) // Get rotation quaternion
{
quat.w=VectorDot(start,end);
CVector3D p;
p=VectorCross(start,end);
quat.x=p.x;
quat.y=p.y;
quat.z=p.z;
}
};
CQuaternion q=arcball_quat*current_quat;
CMatrix3D rot_mat;
q.GetRotationMatrix(rot_mat);
glMultMatrixf((float *)&rot_mat);
void mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON)
{
if (state == GLUT_DOWN)
{
rotation_mode=true;
arc_ball.SetStartPoint(x, y);
}
else
{
rotation_mode=false;
current_quat=arcball_quat*current_quat;
arcball_quat.SetIdentity();
}
}
}
void mouse_motion(int x, int y)
{
if (rotation_mode)
{
arc_ball.SetEndPoint(x, y);
arc_ball.GetQuaternion(arcball_quat);
glutPostRedisplay();
}
}
i