zoukankan      html  css  js  c++  java
  • OpenGL编程逐步深入(七)旋转变换

    准备知识

    这一节我们来看一下旋转变换。旋转变换指的是给我们一个指点的点和角度,我们需要绕着过该点的轴线將对象旋转对应的角度。这里我们只改变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
    ", 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'
    ", ShaderType, InfoLog);
            exit(1);
        }
    
        glAttachShader(ShaderProgram, ShaderObj);
    }
    
    static void CompileShaders()
    {
        GLuint ShaderProgram = glCreateProgram();
    
        if (ShaderProgram == 0) {
            fprintf(stderr, "Error creating shader program
    ");
            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'
    ", 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'
    ", 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'
    ", glewGetErrorString(res));
            return 1;
        }
    
        printf("GL version: %s
    ", 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;

    运行效果

    可以看到三角形在屏幕上不停旋转。

    这里写图片描述

  • 相关阅读:
    shell 10流程控制
    shell 9test命令
    shell 8字符串与文件内容处理
    shell 7输入输出
    shell 6基本运算符
    JS-JQ实现TAB选项卡
    JS-JQ实现页面滚动时元素智能定位(顶部-其他部位)
    js获取框架(IFrame)的内容
    codeforces 660C C. Hard Process(二分)
    codeforces 660B B. Seating On Bus(模拟)
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468964.html
Copyright © 2011-2022 走看看