OpenGL编程逐步深入(七)旋转变换
2015-04-23 20:27
459 查看
准备知识
这一节我们来看一下旋转变换。旋转变换指的是给我们一个指点的点和角度,我们需要绕着过该点的轴线將对象旋转对应的角度。这里我们只改变X/Y/Z中的两个分量,第三个分量保持不变。这意味着我们的图形只在三个平面内旋转:XY平面(绕着Z轴)、YZ平面(绕着X轴)、XZ(绕着Y轴)。还有更复杂的旋转方式这里我们暂时用不到。我们来概括性的定义这个问题。考虑下面这样的图形:
我们需要沿着圆把点(x1,y2)移动到(x2,y2),换句话说就是把(x1,y1)旋转a2角度。我们假定圆的半径为1,则有:
使用正余弦展开公式:
可得:
在上面的图形中,Z轴垂直于屏幕,XY平面和屏幕重合。和平移变换一样,我们4x4阶矩阵和顶点分量矩阵乘积的形式表示该变换,可以写成:
绕Y轴选择可以用以下形式表示:
绕X轴旋转:
上面的4x4阶矩阵就是我们的旋转变换矩阵。
程序代码
/* Copyright 2010 Etay Meiri This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Tutorial 07 - Rotation transformation */ #include "stdafx.h" #include <stdio.h> #include <string.h> #include <assert.h> #include <math.h> #include <GL/glew.h> #include <GL/freeglut.h> #include "ogldev_math_3d.h" GLuint VBO; GLuint gWorldLocation; const char* pVSFileName = "shader.vs"; const char* pFSFileName = "shader.fs"; static void RenderSceneCB() { glClear(GL_COLOR_BUFFER_BIT); static float Scale = 0.0f; Scale += 0.001f; Matrix4f World; World.m[0][0] = cosf(Scale); World.m[0][1] = -sinf(Scale); World.m[0][2] = 0.0f; World.m[0][3] = 0.0f; World.m[1][0] = sinf(Scale); World.m[1][1] = cosf(Scale); World.m[1][2] = 0.0f; World.m[1][3] = 0.0f; World.m[2][0] = 0.0f; World.m[2][1] = 0.0f; World.m[2][2] = 1.0f; World.m[2][3] = 0.0f; World.m[3][0] = 0.0f; World.m[3][1] = 0.0f; World.m[3][2] = 0.0f; World.m[3][3] = 1.0f; glUniformMatrix4fv(gWorldLocation, 1, GL_TRUE, &World.m[0][0]); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, VBO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableVertexAttribArray(0); glutSwapBuffers(); } static void InitializeGlutCallbacks() { glutDisplayFunc(RenderSceneCB); glutIdleFunc(RenderSceneCB); } static void CreateVertexBuffer() { Vector3f Vertices[3]; Vertices[0] = Vector3f(-1.0f, -1.0f, 0.0f); Vertices[1] = Vector3f(1.0f, -1.0f, 0.0f); Vertices[2] = Vector3f(0.0f, 1.0f, 0.0f); glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); } static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType) { GLuint ShaderObj = glCreateShader(ShaderType); if (ShaderObj == 0) { fprintf(stderr, "Error creating shader type %d\n", ShaderType); exit(1); } const GLchar* p[1]; p[0] = pShaderText; GLint Lengths[1]; Lengths[0]= strlen(pShaderText); glShaderSource(ShaderObj, 1, p, Lengths); glCompileShader(ShaderObj); GLint success; glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success); if (!success) { GLchar InfoLog[1024]; glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog); fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog); exit(1); } glAttachShader(ShaderProgram, ShaderObj); } static void CompileShaders() { GLuint ShaderProgram = glCreateProgram(); if (ShaderProgram == 0) { fprintf(stderr, "Error creating shader program\n"); exit(1); } string vs, fs; if (!ReadFile(pVSFileName, vs)) { exit(1); }; if (!ReadFile(pFSFileName, fs)) { exit(1); }; AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER); AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER); GLint Success = 0; GLchar ErrorLog[1024] = { 0 }; glLinkProgram(ShaderProgram); glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success); if (Success == 0) { glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog); fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog); exit(1); } glValidateProgram(ShaderProgram); glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success); if (!Success) { glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog); fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog); exit(1); } glUseProgram(ShaderProgram); gWorldLocation = glGetUniformLocation(ShaderProgram, "gWorld"); assert(gWorldLocation != 0xFFFFFFFF); } int _tmain(int argc, _TCHAR* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA); glutInitWindowSize(1024, 768); glutInitWindowPosition(100, 100); glutCreateWindow("Tutorial 07"); InitializeGlutCallbacks(); // Must be done after glut is initialized! GLenum res = glewInit(); if (res != GLEW_OK) { fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res)); return 1; } printf("GL version: %s\n", glGetString(GL_VERSION)); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); CreateVertexBuffer(); CompileShaders(); glutMainLoop(); return 0; }
代码解读
这里我们只把矩阵改成旋转变换矩阵,其余代码和上节相同。World.m[0][0]=cosf(Scale); World.m[0][1]=-sinf(Scale); World.m[0][2]=0.0f; World.m[0][3]=0.0f; World.m[1][0]=sinf(Scale); World.m[1][1]=cosf(Scale); World.m[1][2]=0.0f; World.m[1][3]=0.0f; World.m[2][0]=0.0f; World.m[2][1]=0.0f; World.m[2][2]=1.0f; World.m[2][3]=0.0f; World.m[3][0]=0.0f; World.m[3][1]=0.0f; World.m[3][2]=0.0f; World.m[3][3]=1.0f;
运行效果
可以看到三角形在屏幕上不停旋转。相关文章推荐
- OpenGL编程逐步深入(七)旋转变换
- OpenGL编程逐步深入(七)旋转变换
- OpenGL编程逐步深入(二)在窗口中显示一个点
- OpenGL编程逐步深入(八)伸缩变换
- OpenGL编程逐步深入(九)插值处理
- OpenGL编程逐步深入(十一)组合变换
- OpenGL编程逐步深入(二)在窗口中显示一个点
- OpenGL编程逐步深入(五)Uniform 变量
- OpenGL编程逐步深入(八)伸缩变换
- OpenGL编程逐步深入(九)插值处理
- OpenGL编程逐步深入(二)在窗口中显示一个点
- OpenGL编程逐步深入(五)Uniform 变量
- OpenGL编程逐步深入(五)Uniform 变量
- OpenGL编程逐步深入(九)插值处理
- OpenGL编程逐步深入(三)在窗口中显示一个三角形
- OpenGL编程逐步深入(三)在窗口中显示一个三角形
- OpenGL编程逐步深入(一)创建一个窗口
- OpenGL编程逐步深入(三)在窗口中显示一个三角形
- OpenGL编程逐步深入(四)Shaders
- OpenGL编程逐步深入(十)索引绘制