C++ OpenGL-使用四元数环绕点的摄影机

C++ OpenGL-使用四元数环绕点的摄影机,c++,opengl,camera,rotation,quaternions,C++,Opengl,Camera,Rotation,Quaternions,因此,我目前使用四元数来存储和修改OpenGL场景中对象的方向,以及摄影机的方向。当直接旋转这些对象时(即说我想绕Z轴旋转摄影机Z量,或者我想绕X轴旋转对象X,然后沿其局部Z轴平移对象T),我没有问题,因此我只能假设我的基本旋转代码是正确的 然而,我现在正试图实现一个功能,使我的相机在太空中的任意点轨道,并有相当困难的时间。这是我到目前为止提出的,但不起作用(这发生在Camera类中) //获取方向的倒数,它应该表示方向 //“从”焦点到相机 四元数逆方向=m_方向; InverseOrient

因此,我目前使用四元数来存储和修改OpenGL场景中对象的方向,以及摄影机的方向。当直接旋转这些对象时(即说我想绕Z轴旋转摄影机Z量,或者我想绕X轴旋转对象X,然后沿其局部Z轴平移对象T),我没有问题,因此我只能假设我的基本旋转代码是正确的

然而,我现在正试图实现一个功能,使我的相机在太空中的任意点轨道,并有相当困难的时间。这是我到目前为止提出的,但不起作用(这发生在Camera类中)

//获取方向的倒数,它应该表示方向
//“从”焦点到相机
四元数逆方向=m_方向;
InverseOrient.inverse();
///轮换
//为每个轴创建更改四元数
四元数xOffset=四元数();
x轴角偏移量(xChange*m_转速,1.0,0.0,0.0);
四元数yOffset=四元数();
Y轴角偏移量(Y变化*m_转速,0.0,1.0,0.0);
四元数zOffset=四元数();
轴角(zChange*m_转速,0.0,0.0,1.0);
//将更改四分之一乘以反转方向四分之一
反向定向=yOffset*zOffset*xOffset*InverseOrient;
//根据焦距进行平移
//从相对于被观察位置的向量开始
矢量3相对论(0,0,-m_焦距);
//根据四元数旋转
RelativePos=逆方向多重投影(RelativePos);
//将该相对位置添加到焦点
m_Position.x=m_FocalPoint->x+RelativePos.x;
m_Position.y=m_FocalPoint->y+RelativePos.y;
m_Position.z=m_FocalPoint->z+RelativePos.z;
//现在将方向设置为四元数的倒数
//用于定位相机
m_方向=反向方向;
m_方向。反转();
最终发生的是,相机围绕其他点旋转——当然不是物体,但显然也不是物体本身,就好像它以螺旋路径在空间中循环


因此,这显然不是围绕一个点旋转相机的方法,而是什么呢?

我将首先在球坐标中操作相机,并根据需要转换为四元数

鉴于以下假设:

  • 这架照相机没有镜头
  • 你看到的点是[x,y,z]
  • 你有偏航角,俯仰角
  • [0,1,0]处于“上升”状态
以下是如何计算一些重要值:

  • 视图向量:v=[vx,vy,vz]=[cos(偏航)*cos(俯仰),sin(俯仰),-sin(偏航)*cos(俯仰)]
  • 摄像机位置:p=[x,y,z]-r*v
  • 右向量:v与[0,1,0]的叉积
  • 上方向向量:与右方向向量的叉积v
  • 视图四元数是[0,vx,vy,vz](这是具有0 w分量的视图向量)
现在在您的模拟中,您可以操作俯仰/偏航,这非常直观。如果要执行插值,请将前后俯仰+偏航转换为四元数,并执行四元数球面线性插值

    //Get the inverse of the orientation, which should represent the orientation 
    //"from" the focal point to the camera
    Quaternion InverseOrient = m_Orientation;
    InverseOrient.Invert();

    ///Rotation
    //Create change quaternions for each axis
    Quaternion xOffset = Quaternion();
    xOffset.FromAxisAngle(xChange * m_TurnSpeed, 1.0, 0.0, 0.0);

    Quaternion yOffset = Quaternion();
    yOffset.FromAxisAngle(yChange * m_TurnSpeed, 0.0, 1.0, 0.0);

    Quaternion zOffset = Quaternion();
    zOffset.FromAxisAngle(zChange * m_TurnSpeed, 0.0, 0.0, 1.0);

    //Multiply the change quats into the inversed orientation quat
    InverseOrient = yOffset * zOffset * xOffset * InverseOrient;

    //Translate according to the focal distance
    //Start with a vector relative to the position being looked at
    sf::Vector3<float> RelativePos(0, 0, -m_FocalDistance);
    //Rotate according to the quaternion
    RelativePos = InverseOrient.MultVect(RelativePos);

    //Add that relative position to the focal point
    m_Position.x = m_FocalPoint->x + RelativePos.x;
    m_Position.y = m_FocalPoint->y + RelativePos.y;
    m_Position.z = m_FocalPoint->z + RelativePos.z;

    //Now set the orientation to the inverse of the quaternion 
    //used to position the camera
    m_Orientation = InverseOrient;
    m_Orientation.Invert();