用于透视投影的相机旋转
我刚刚开始使用 OpenGL 来渲染多个结构,每个结构都包含多个多边形。 基本上我想执行相当于在世界(结构)坐标中将相机设置在(0,0,z)处并绕世界轴的x,y和z轴(按顺序!)旋转以渲染每个结构的视图(据我了解,通常的做法是使用逆相机矩阵)。因此,据我了解,我需要翻译(到世界原点,即(0,0,-z))*rotateZrotateYrotateX*翻译(重新定义世界原点见下文)
所以我认为我需要类似的东西:
//Called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(9.148, (double)w / (double)h, 800.0, 1500.0);
}
float _Zangle = 10.0f;
float _cameraAngle = 90.0f;
//Draws the 3D scene
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glTranslatef(0.0f, 0.0f, -z); //Move forward Z (mm) units
glRotatef(-_Zangle, 0.0f, 0.0f, 1.0f); //Rotate "camera" about the z-axis
glRotatef(-_cameraAngle, 0.0f, 1.0f, 0.0f); //Rotate the "camera" by camera_angle about y-axis
glRotatef (90.0f,1.0f,0.0f,0.0f); // rotate "camera" by 90 degrees about x-axis
glTranslatef(-11.0f,189.0f,51.0f); //re-define origin of world coordinates to be (11,-189,-51) - applied to all polygon vertices
glPushMatrix(); //Save the transformations performed thus far
glBegin(GL_POLYGON);
glVertex3f(4.91892,-225.978,-50.0009);
glVertex3f(5.73534,-225.978,-50.0009);
glVertex3f(6.55174,-225.978,-50.0009);
glVertex3f(7.36816,-225.978,-50.0009);
.......// etc
glEnd();
glPopMatrix();
但是,当我编译并运行它时,_angle 和 _cameraAngle 似乎颠倒了,即 _angle 似乎围绕视口的 y 轴(垂直)旋转,而 _cameraAngle 围绕 z 轴(进入视口的平面)旋转?我做错了什么?
感谢您花时间阅读本文
I've just started playing with OpenGl to render a number of structure each comprising a number of polygon.
Basically I want to perform the equivalent of setting a camera at (0,0,z) in the world (structure) coordinates and rotate it about the x,y and z-axes of the world axes (in that order!) to render a view of each structure (as I understand it it common practice to do use the inverse camera matrix). Thus as I understand it I need to translate (to world origin i.e. (0,0,-z)) * rotateZrotateYrotateX * translate (re-define world origin see below)
So I think I need something like:
//Called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(9.148, (double)w / (double)h, 800.0, 1500.0);
}
float _Zangle = 10.0f;
float _cameraAngle = 90.0f;
//Draws the 3D scene
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glTranslatef(0.0f, 0.0f, -z); //Move forward Z (mm) units
glRotatef(-_Zangle, 0.0f, 0.0f, 1.0f); //Rotate "camera" about the z-axis
glRotatef(-_cameraAngle, 0.0f, 1.0f, 0.0f); //Rotate the "camera" by camera_angle about y-axis
glRotatef (90.0f,1.0f,0.0f,0.0f); // rotate "camera" by 90 degrees about x-axis
glTranslatef(-11.0f,189.0f,51.0f); //re-define origin of world coordinates to be (11,-189,-51) - applied to all polygon vertices
glPushMatrix(); //Save the transformations performed thus far
glBegin(GL_POLYGON);
glVertex3f(4.91892,-225.978,-50.0009);
glVertex3f(5.73534,-225.978,-50.0009);
glVertex3f(6.55174,-225.978,-50.0009);
glVertex3f(7.36816,-225.978,-50.0009);
.......// etc
glEnd();
glPopMatrix();
However when I compile and run this the _angle and _cameraAngle seem to be reversed i.e. _angle seems to rotate about y-axis (Vertical) of Viewport and _cameraAngle about z-axis (into plane of Viewport)? What am I doing wrong?
Thanks for taking the time to read this
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
简短的答案是:使用 gluLookAt()。该实用函数创建正确的观察矩阵。
更长的答案是,每个 OpenGL 变换调用都采用当前矩阵并将其乘以为完成变换而构建的矩阵。通过调用一系列 OpenGL 变换函数,您可以构建一个将应用变换组合的变换矩阵。实际上,矩阵将为 M = M1 * M2 * M3 。 。 。从数学上讲,变换在上式中是从右到左应用的。
您的代码不会移动相机。它停留在原点,并向下看负 z 轴。您的转换将模型空间中的所有内容移动到 (11,-189,-51),将所有内容绕 x 轴旋转 90 度,将所有内容绕 y 轴旋转 90 度,将所有内容绕 z 轴旋转 10 度,然后进行平移沿 z 轴的所有
-z
内容。编辑:更多信息
我对您想要完成的任务有点困惑,但我认为您希望在原点拥有元素,并让相机查看这些元素。眼睛坐标将是您想要相机所在的位置,中心坐标将是您想要对象所在的位置。我会使用一点三角学来计算相机的位置,并将其指向原点。
在这种情况下,我通常使用以原点为中心的经度、纬度和海拔来跟踪相机位置。计算眼睛坐标的 x、y、z 很简单:x = elv * cos(lat) * sin(lon)、y = elv * sin(lat)、z = elv * cos(lat) * cos(lat)。
我的 gluLookAt 调用将是 gluLookAt(x, y, z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
您可以通过更改 gluLookAt 的最后三个坐标来向上旋转相机。
The short answer is: Use gluLookAt(). This utility function creates the proper viewing matrix.
The longer answer is that each OpenGL transformation call takes the current matrix and multiplies it by a matrix built to accomplish the transformation. By calling a series of OpenGL transformation function you build one transformation matrix that will apply the combination of transformations. Effectively, the matrix will be M = M1 * M2 * M3 . . . Mathematically, the transformations are applied from right to left in the above equation.
Your code doesn't move the camera. It stays at the origin, and looks down the negative z-axis. Your transformations move everything in model space to (11,-189,-51), rotates everything 90 degrees about the x-axis, rotates everything 90 degrees about the y-axis, rotates everything 10 degrees about the z-axis, then translates everything
-z
along the z-axis.EDIT: More information
I'm a little confused about what you want to accomplish, but I think you want to have elements at the origin, and have the camera look at those elements. The eye coordinates would be where you want the camera, and the center coordinates would be where you want the objects to be. I'd use a little trigonometry to calculate the position of the camera, and point it at the origin.
In this type of situation I usually keep track of camera position using longitude, latitude, and elevation centered on the origin. Calculating x,y,z for the eye coordinates is simplyx = elv * cos(lat) * sin(lon), y = elv * sin(lat), z = elv * cos(lat) * cos(lat).
My gluLookAt call would be
gluLookAt(x, y, z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
You could rotate the up on the camera by changing the last three coordinates for gluLookAt.
z 轴从显示器的中心指向您。因此,绕 z 轴旋转应该使相机旋转到位(就像仅在 xy 平面上进行 2D 旋转)。我不知道,但这就是这里发生的事情吗?
The z axis is coming from the center of the monitor into you. So, rotating around the z-axis should make the camera spin in place (like a 2D rotation on just the xy plane). I can't tell, but is that what's happening here?
您可能遇到了万向节锁。尝试删除其中一项轮换,看看事情是否按应有的方式进行。
虽然您确实无法在 OpenGL 中实际移动相机,但您可以通过移动其他所有内容来模拟相机运动。这就是您听说逆相机矩阵的原因。我们可以将世界上的所有物体移动 (0, 0, -10),而不是将相机移动 (0, 0, 10)。如果将它们展开为矩阵,您会发现它们是互逆的。
我还注意到,鉴于所提供的代码,您不需要
glPushMatrix()
/glPopMatrix()
调用。也许有一些您尚未展示的代码需要它们。最后,您能提供一下您要渲染的内容吗?如果没有一些上下文,调试旋转可能会很困难。
It's possible that you are encountering Gimbal Lock. Try removing one of the rotations and see if things work the way they should.
While it's true that you can't actually move the camera in OpenGL, you can simulate camera motion by moving everything else. This is why you hear about the inverse camera matrix. Instead of moving the camera by (0, 0, 10), we can move everything in the world by (0, 0, -10). If you expand those out into matrices, you will find that they are inverses of each other.
I also noticed that, given the code presented, you don't need the
glPushMatrix()
/glPopMatrix()
calls. Perhaps there is code that you haven't shown that requires them.Finally, can you provide an idea of what it is you are trying to render? Debugging rotations can be hard without some context.
简短答案:好提示
较长答案:是的,矩阵乘法的顺序很清楚......这就是我所说的逆相机矩阵的意思,表示将结构的所有世界坐标移动到相机坐标中(因此在我的中使用“相机”)评论;-)) 而不是实际将相机平移和旋转到世界坐标中。
因此,如果我正确地阅读了字里行间,你会提出这样的建议:
或者我仍然遗漏了什么?
Short answer :Good tip
Longer answer: Yes the order of matrix multiplication is clear... that's what I meant by inverse camera matrix to indicate moving all the world coordinates of structures into the camera coordinates (hence the use of "camera" in my comments ;-)) instead of actually translating and rotating camera into the world coordinates.
So if I read between the lines correctly you suggest something like:
Or am I still missing something?
我认为您将世界的轴与相机的轴混合在一起,
GLRotatef 仅使用相机的轴,一旦相机旋转,它们就与您的世界轴不同。
I think you are mixing axes of your world with axes of the camera,
GLRotatef only uses axes of the camera, they are not the same as your the world axes once the camera is rotated.