在 opengl 中获取 arcball 的正确屏幕映射
我正在尝试实现一个轨迹球界面,似乎在旋转 90 度后模型停止沿该特定方向旋转,我怀疑将屏幕上的点击映射到轨迹球存在问题,但这可能是错误的数学和/或错误的转换累积,任何帮助将不胜感激,这里是问题的相关代码,在向量上操作时^运算符表示叉积,*运算符表示内积
void mouseButton(int button,int state,int x,int y){
if(state==GLUT_DOWN){
GLdouble xx,yy,zz;
GLdouble modelMatrix[16];
glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
GLdouble projMatrix[16];
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
int viewport[4];
glGetIntegerv(GL_VIEWPORT,viewport);
gluUnProject(x,height-y-1,0.755
,modelMatrix,projMatrix,viewport,&xx,&yy,&zz);
arcBall_begin(xx,yy);
}
}
void mouseMotion(int x,int y){
GLdouble xx,yy,zz;
GLdouble modelMatrix[16];
glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
GLdouble projMatrix[16];
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
int viewport[4];
glGetIntegerv(GL_VIEWPORT,viewport);
gluUnProject(x,height-y-1,0.755
,modelMatrix,projMatrix,viewport,&xx,&yy,&zz);
arcBall_drag(xx,yy);
}
void arcBall_begin(GLdouble x,GLdouble y){
if(sqrt((x*x)+(y*y))>radius)
begin = vec(x,y,0);
else
begin = vec(x,y,sqrt((radius*radius)-(x*x)-(y*y)));
begin = begin.unit();
glGetDoublev(GL_MODELVIEW_MATRIX,mm);
}
void arcBall_drag(GLdouble x,GLdouble y){
if(sqrt((x*x)+(y*y))>radius)
end = vec(x,y,0);
else
end = vec(x,y,sqrt((radius*radius)-(x*x)-(y*y)));
end = end.unit();
rotationAxis = begin^end;
rotationAxis = rotationAxis.unit();
angle = -2*acos(begin*end);
angle = angle * (float(180)/float(PI));
}
float arcBall_rotate(){
if(angle!=0.0){
glLoadMatrixd(mm);
glRotatef(angle,rotationAxis.x,rotationAxis.y,rotationAxis.z);
angle = 0.0;
}
return angle;
}
I am trying to implement an arcball interface and it seems that after rotation of 90 degrees the model stops rotating in that specific direction, I suspect that there is a problem with mapping clicks on the screen to the arcball, but it could be wrong math and/or wrong transformations accumulation, any help would be appreciated, here is the relevant code for the problem, when operating on vectors the ^ operator represents cross product, and * operator represents inner product
void mouseButton(int button,int state,int x,int y){
if(state==GLUT_DOWN){
GLdouble xx,yy,zz;
GLdouble modelMatrix[16];
glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
GLdouble projMatrix[16];
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
int viewport[4];
glGetIntegerv(GL_VIEWPORT,viewport);
gluUnProject(x,height-y-1,0.755
,modelMatrix,projMatrix,viewport,&xx,&yy,&zz);
arcBall_begin(xx,yy);
}
}
void mouseMotion(int x,int y){
GLdouble xx,yy,zz;
GLdouble modelMatrix[16];
glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
GLdouble projMatrix[16];
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
int viewport[4];
glGetIntegerv(GL_VIEWPORT,viewport);
gluUnProject(x,height-y-1,0.755
,modelMatrix,projMatrix,viewport,&xx,&yy,&zz);
arcBall_drag(xx,yy);
}
void arcBall_begin(GLdouble x,GLdouble y){
if(sqrt((x*x)+(y*y))>radius)
begin = vec(x,y,0);
else
begin = vec(x,y,sqrt((radius*radius)-(x*x)-(y*y)));
begin = begin.unit();
glGetDoublev(GL_MODELVIEW_MATRIX,mm);
}
void arcBall_drag(GLdouble x,GLdouble y){
if(sqrt((x*x)+(y*y))>radius)
end = vec(x,y,0);
else
end = vec(x,y,sqrt((radius*radius)-(x*x)-(y*y)));
end = end.unit();
rotationAxis = begin^end;
rotationAxis = rotationAxis.unit();
angle = -2*acos(begin*end);
angle = angle * (float(180)/float(PI));
}
float arcBall_rotate(){
if(angle!=0.0){
glLoadMatrixd(mm);
glRotatef(angle,rotationAxis.x,rotationAxis.y,rotationAxis.z);
angle = 0.0;
}
return angle;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请记住,在 OpenGL 中,像素坐标是 (0,0) 位于屏幕的左上角,因此当您想要映射时,必须反转 y 轴以将坐标映射到球体。
Remember that in OpenGL pixel coordinates are (0,0) in the upper left corner of the screen, so when you want to map you have to reverse the y axis to map the coordinates to a sphere.