OpenGl 平移和旋转

标签: OpenGl opengl 2d graphic tutorial 发布于:2020-04-12 16:00:53 编辑于:2022-11-15 12:18:50 浏览量:32093

OpenGL 二维图形学教程系列

此系列翻译自:OpenGL Tutorial An Introduction on OpenGL with 2D Graphics

  1. OpenGl 环境搭建与介绍
  2. OpenGl 顶点,图元以及颜色
  3. OpenGL 裁剪区域与视口
  4. OpenGl 平移和旋转
  5. OpenGl 动画
  6. OpenGL 使用 GLUT 处理键盘输入
  7. OpenGL 使用 GLUT 处理鼠标输入

5. 平移和旋转

在上述例子中,我们通过指定顶点来摆放形状,而这些顶点都参照同一个坐标原点,即在所谓的世界坐标系下进行定义。我花了很长时间才弄清楚这些顶点的绝对坐标。

这无疑不是很方便,我们可以通过参照图形自身的中心来定义其顶点,即在所谓的模型坐标系下进行定义。之后我们可以使用平移和旋转来在世界坐标系下将图形摆放到目标位置。

5.1 例子 4:平移与旋转(GL04ModelTransform.cpp)

/*
 * GL04ModelTransform.cpp: Model Transform - Translation and Rotation
 * Transform primitives from their model spaces to world space.
 */
#include <windows.h>  // for MS Windows
#include <GL/glut.h>  // GLUT, include glu.h and gl.h
 
/* Initialize OpenGL Graphics */
void initGL() {
   // Set "clearing" or background color
   glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black and opaque
}
 
/* Handler for window-repaint event. Call back when the window first appears and
   whenever the window needs to be re-painted. */
void display() {
   glClear(GL_COLOR_BUFFER_BIT);    // Clear the color buffer
   glMatrixMode(GL_MODELVIEW);      // To operate on Model-View matrix
   glLoadIdentity();                // Reset the model-view matrix
 
   glTranslatef(-0.5f, 0.4f, 0.0f); // Translate left and up
   glBegin(GL_QUADS);               // Each set of 4 vertices form a quad
      glColor3f(1.0f, 0.0f, 0.0f);  // Red
      glVertex2f(-0.3f, -0.3f);     // Define vertices in counter-clockwise (CCW) order
      glVertex2f( 0.3f, -0.3f);     //  so that the normal (front-face) is facing you
      glVertex2f( 0.3f,  0.3f);
      glVertex2f(-0.3f,  0.3f);
   glEnd();
 
   glTranslatef(0.1f, -0.7f, 0.0f); // Translate right and down
   glBegin(GL_QUADS);               // Each set of 4 vertices form a quad
      glColor3f(0.0f, 1.0f, 0.0f); // Green
      glVertex2f(-0.3f, -0.3f);
      glVertex2f( 0.3f, -0.3f);
      glVertex2f( 0.3f,  0.3f);
      glVertex2f(-0.3f,  0.3f);
   glEnd();
 
   glTranslatef(-0.3f, -0.2f, 0.0f); // Translate left and down
   glBegin(GL_QUADS);                // Each set of 4 vertices form a quad
      glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
      glVertex2f(-0.2f, -0.2f);
      glColor3f(1.0f, 1.0f, 1.0f); // White
      glVertex2f( 0.2f, -0.2f);
      glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
      glVertex2f( 0.2f,  0.2f);
      glColor3f(1.0f, 1.0f, 1.0f); // White
      glVertex2f(-0.2f,  0.2f);
   glEnd();
 
   glTranslatef(1.1f, 0.2f, 0.0f); // Translate right and up
   glBegin(GL_TRIANGLES);          // Each set of 3 vertices form a triangle
      glColor3f(0.0f, 0.0f, 1.0f); // Blue
      glVertex2f(-0.3f, -0.2f);
      glVertex2f( 0.3f, -0.2f);
      glVertex2f( 0.0f,  0.3f);
   glEnd();
 
   glTranslatef(0.2f, -0.3f, 0.0f);     // Translate right and down
   glRotatef(180.0f, 0.0f, 0.0f, 1.0f); // Rotate 180 degree
      glBegin(GL_TRIANGLES);               // Each set of 3 vertices form a triangle
      glColor3f(1.0f, 0.0f, 0.0f); // Red
      glVertex2f(-0.3f, -0.2f);
      glColor3f(0.0f, 1.0f, 0.0f); // Green
      glVertex2f( 0.3f, -0.2f);
      glColor3f(0.0f, 0.0f, 1.0f); // Blue
      glVertex2f( 0.0f,  0.3f);
   glEnd();
 
   glRotatef(-180.0f, 0.0f, 0.0f, 1.0f); // Undo previous rotate
   glTranslatef(-0.1f, 1.0f, 0.0f);      // Translate right and down
   glBegin(GL_POLYGON);                  // The vertices form one closed polygon
      glColor3f(1.0f, 1.0f, 0.0f); // Yellow
      glVertex2f(-0.1f, -0.2f);
      glVertex2f( 0.1f, -0.2f);
      glVertex2f( 0.2f,  0.0f);
      glVertex2f( 0.1f,  0.2f);
      glVertex2f(-0.1f,  0.2f);
      glVertex2f(-0.2f,  0.0f);
   glEnd();
 
   glFlush();   // Render now
}
 
/* Handler for window re-size event. Called back when the window first appears and
   whenever the window is re-sized with its new width and height */
void reshape(GLsizei width, GLsizei height) {  // GLsizei for non-negative integer
   // Compute aspect ratio of the new window
   if (height == 0) height = 1;                // To prevent divide by 0
   GLfloat aspect = (GLfloat)width / (GLfloat)height;
 
   // Set the viewport to cover the new window
   glViewport(0, 0, width, height);
 
   // Set the aspect ratio of the clipping area to match the viewport
   glMatrixMode(GL_PROJECTION);  // To operate on the Projection matrix
   glLoadIdentity();
   if (width >= height) {
     // aspect >= 1, set the height from -1 to 1, with larger width
      gluOrtho2D(-1.0 * aspect, 1.0 * aspect, -1.0, 1.0);
   } else {
      // aspect < 1, set the width to -1 to 1, with larger height
     gluOrtho2D(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect);
   }
}
 
/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv) {
   glutInit(&argc, argv);          // Initialize GLUT
   glutInitWindowSize(640, 480);   // Set the window's initial width & height - non-square
   glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
   glutCreateWindow("Model Transform");  // Create window with the given title
   glutDisplayFunc(display);       // Register callback handler for window re-paint event
   glutReshapeFunc(reshape);       // Register callback handler for window re-size event
   initGL();                       // Our own OpenGL initialization
   glutMainLoop();                 // Enter the infinite event-processing loop
   return 0;
}
glMatrixMode(GL_MODELVIEW); // To operate on model-view matrix
glLoadIdentity();           // Reset

平移与旋转是所谓的模型变换的一部分,其将模型从模型坐标系下转换到世界坐标系。要想进行模型变换,我们需要首先将当前矩阵模式设置为模型视图矩阵(GL_MODELVIEW)并将其重置为单位矩阵。

OpenGL 作为状态机运行。也就是说,一旦状态被设置,该状态持续存在除非其被改变。结合此处的例子,一旦坐标被平移或旋转了,所有后续的操作都会基于这些被平移或旋转后的坐标。

通过 glTranslate 函数来进行平移:

void gltranslatef (GLfloat x, GLfloat y, GLfloat z)
   // where (x, y, z) is the translational vector

注意glTranslatef 函数必须要放置在 glBegin/glEnd 的外面,而glColor 函数则可以放置在glBegin/glEnd里面。

通过glRotatef 函数来进行旋转:

void glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
   // where angle specifies the rotation in degree, (x, y, z) forms the axis of rotation

注意旋转的角度的单位为度,而非弧度。

在上述例子中,我们在 x-y 平面对物体进行了平移操作,并围绕 z 轴旋转物体。

未经允许,禁止转载,本文源站链接:https://iamazing.cn/