Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 四元数FPS相机_Opengl_Camera_Glut_Frame Rate_Quaternions - Fatal编程技术网

Opengl 四元数FPS相机

Opengl 四元数FPS相机,opengl,camera,glut,frame-rate,quaternions,Opengl,Camera,Glut,Frame Rate,Quaternions,我正在尝试用GLUT和OpenGL创建一个FPS风格的相机。我被引导到这个特别的教程,我已经尝试遵循 对作者的代码做了一些小改动(我有一个不同的四元数类,处理函数的方式略有不同),下面是我的代码: void RotateCamera(double Angle, double x, double y, double z) { //quaternions in the form of w,x,y,z quaternion temp(cos(Angle/2), x*sin(Angle/2),

我正在尝试用GLUT和OpenGL创建一个FPS风格的相机。我被引导到这个特别的教程,我已经尝试遵循

对作者的代码做了一些小改动(我有一个不同的四元数类,处理函数的方式略有不同),下面是我的代码:

void RotateCamera(double Angle, double x, double y, double z)
{
  //quaternions in the form of w,x,y,z
  quaternion temp(cos(Angle/2), x*sin(Angle/2), y * sin(Angle/2),z * sin(Angle/2) );
  quaternion quat_view(0, view.x, view.y, view.z);
  quaternion result = operator*(operator*(temp, quat_view), temp.conjugate());
  view = result.vector();
}


void SetViewByMouse(int MouseX, int MouseY)
{

  // the middle of the screen in the x direction
  int MiddleX = G308_WIN_WIDTH/2;

  // the middle of the screen in the y direction
  int MiddleY = G308_WIN_HEIGHT/2;

  // vector that describes mouseposition - center
  G308_Point mouse_direction;
  mouse_direction.x = 0.0f;
  mouse_direction.y = 0.0f;
  mouse_direction.z = 0.0f;

  // static variable to store the rotation about the x-axis, since
  // we want to limit how far up or down we can look.
  // We don't need to cap the rotation about the y-axis as we
  // want to be able to turn around 360 degrees
  static double CurrentRotationX = 0.0;

  // The maximum angle we can look up or down, in radians
  double maxAngle = 1;


  // if the mouse hasn't moved, return without doing
  // anything to our view
  if((MouseX == MiddleX) && (MouseY == MiddleY))
    return;

  // otherwise move the mouse back to the middle of the screen
  glutWarpPointer(MiddleX, MiddleY);

  // get the distance and direction the mouse moved in x (in
  // pixels). We can't use the actual number of pixels in radians,
  // as only six pixels  would cause a full 360 degree rotation.
  // So we use a mousesensitivity variable that can be changed to
  // vary how many radians we want to turn in the x-direction for
  // a given mouse movement distance

  // We have to remember that positive rotation is counter-clockwise.
  // Moving the mouse down is a negative rotation about the x axis
  // Moving the mouse right is a negative rotation about the y axis
  mouse_direction.x = float((MiddleX - MouseX)/mouse_sensitivity);
  mouse_direction.y = float((MiddleY - MouseY)/mouse_sensitivity);

  CurrentRotationX += mouse_direction.y;

  // We don't want to rotate up more than one radian, so we cap it.
  if(CurrentRotationX > 1)
  {
    CurrentRotationX = 1;
    return;
  }
  // We don't want to rotate down more than one radian, so we cap it.
  if(CurrentRotationX < -1)
  {
    CurrentRotationX = -1;
    return;
  }
  else
  {
    // get the axis to rotate around the x-axis.
    G308_Point Axis = crossProduct(subtract(view,position), up);
    // To be able to use the quaternion conjugate, the axis to
    // rotate around must be normalized.
    Axis = normalise(Axis);

    // Rotate around the y axis
    RotateCamera(mouse_direction.y, Axis.x, Axis.y, Axis.z);
    // Rotate around the x axis
    RotateCamera(mouse_direction.x, 0, 1, 0);
  }

  glutPostRedisplay();
}
void RotateCamera(双角度、双x、双y、双z)
{
//w,x,y,z形式的四元数
四元数温度(cos(角度/2)、x*sin(角度/2)、y*sin(角度/2)、z*sin(角度/2));
四元数四元视图(0,view.x,view.y,view.z);
四元数结果=运算符*(运算符*(临时,四元视图),临时共轭();
view=result.vector();
}
void SetViewByMouse(int-MouseX,int-MouseY)
{
//x方向上屏幕的中间部分
int MIDLEX=G308_WIN_WIDTH/2;
//y方向上屏幕的中间部分
int MIDLEY=G308_WIN_HEIGHT/2;
//描述鼠标位置的向量-中心
G308_点鼠标_方向;
鼠标方向x=0.0f;
鼠标方向y=0.0f;
鼠标方向z=0.0f;
//用于存储绕x轴旋转的静态变量,因为
//我们想限制我们能往上或向下看多远。
//我们不需要在旋转时限制绕y轴的旋转
//想要能够360度旋转吗
静态双电流旋转X=0.0;
//我们可以向上或向下看的最大角度,以弧度为单位
双maxAngle=1;
//如果鼠标未移动,则不执行任何操作即可返回
//我们认为怎么样
如果((MouseX==MiddleX)和&(MouseY==MiddleY))
回来
//否则,将鼠标移回屏幕中间
指针(MiddleX,MiddleY);
//获取鼠标在x方向移动的距离和方向(在
//像素)。我们不能使用弧度的实际像素数,
//因为只有六个像素会导致360度旋转。
//因此,我们使用一个mousesensitivity变量,可以将其更改为
//改变我们要在x方向上旋转多少弧度
//给定的鼠标移动距离
//我们必须记住正旋转是逆时针的。
//向下移动鼠标是绕x轴的负旋转
//向右移动鼠标是围绕y轴的负旋转
鼠标方向。x=浮动((MiddleX-MouseX)/鼠标灵敏度);
鼠标方向y=浮动((中间y-鼠标)/鼠标灵敏度);
CurrentRotationX+=鼠标方向y;
//我们不想向上旋转超过一个弧度,所以我们对其进行限制。
如果(CurrentRotationX>1)
{
电流旋转x=1;
回来
}
//我们不想向下旋转超过一个弧度,所以我们将其覆盖。
如果(当前旋转X<-1)
{
CurrentRotationX=-1;
回来
}
其他的
{
//使轴绕x轴旋转。
G308_点轴=叉积(减去(视图、位置),向上);
//为了能够使用四元数共轭,轴
//必须规范化旋转。
轴=法线化(轴);
//绕y轴旋转
RotateCamera(鼠标方向y、轴x、轴y、轴z);
//绕x轴旋转
RotateCamera(鼠标方向x,0,1,0);
}
再发现();
}
我已经制作了交叉积、减法和归一化函数,这些函数应该可以正常工作

问题


运行程序时,它会按预期显示场景,但当我移动鼠标时,它会立即变黑。没什么可继续的了对不起。。。如果有帮助的话,我将鼠标灵敏度设置为0.1。

不确定这是否是您想要的,但让我向您展示我的一个项目中的一些片段

它在我正在使用它的项目的上下文中工作,但是当我提取代码片段时,可能会出现一些错误

// a function to build a quaternion from axis angle
inline Quat rotationAroundAxis(double r,Vec3 a){
    a=normalize(a);
    a*=sin(r/2);
    return Quat(a(0),a(1),a(2),cos(r/2));
}

// read the mouse movement, the important part is to get int dx,dy,dz somehow
int mx,my,mz;
glfwGetMousePos(&mx,&my);
mz=glfwGetMouseWheel();
int dmx=mx-oldMx;
int dmy=my-oldMy;
int dmz=mz-oldMz;
oldMx=mx;
oldMy=my;
oldMz=mz;

// get the current rotation
Quat r=cameraTransform()->getRotation();
//create a vector that encodes these
float sr=time_since_last_frame*100.0f;//sensitivity constant
Vec3 rv(-dmy*0.001*sr,-dmx*0.001*sr,dmz*0.1);
//rotate around the axis formed by the vector -rv with 
//the magnitude of the vectors normal norm(rv) 
Quat rot=normalize(rotationAroundAxis(norm(rv),-rv)*r);
//save the new rotation and update rotation matrix
cameraTransform()->setRotation(rot);

inline Matrix4x4 Transform::setRotation(Quat r){
    rotationQuat=r;//save rotation so we can get it later
    //convert to a rotation matrix and store it
    double x=r.i,y=r.j,z=r.k,w=r.r;
    rotation=matrix(1-2*y*y-2*z*z,2*x*y-2*z*w,2*x*z+2*y*w,0,
                    2*x*y+2*z*w,1-2*x*x-2*z*z,2*y*z-2*x*w,0,
                    2*x*z-2*y*w,2*y*z+2*x*w,1-2*x*x-2*y*y,0,
                    0,0,0,1);
}

// the rotation is later used to compute the transform of the camera to 
//its position in the scene
transform=scale*rotation*translate;

// invert it
worldToEye=transform.inverse();

//setup rendering
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMultMatrixf((float*)&worldToEye);


// DRAW all objects here

我从来没有完全理解过四元数相机的观点,尤其是在FPS中,你试图解决的问题是什么,不能用视图向量和上方向向量来解决,以及用两个叉积来构造矩阵?(请不要说“万向节锁”,因为根本没有这样的东西,四元数也不能解决这个问题。)有时当人们宣传四元数时,我会感到惊讶,因为它实际上只是美化了轴角度…Damon,就我个人而言,我使用它是因为当程序中的所有其他旋转都以这种方式表达时,它更容易推理(虽然考虑到变换的简单性以及最终需要一个矩阵的事实,我仍然不会在相机中使用它们,只需将单位向量填充到它们的位置就容易多了)。@Damon你可以直接用四元数旋转向量,但它比使用导出矩阵需要更多的操作(尤其是对于整个场景)