准备知识

这一节我们来看一下旋转变换。旋转变换指的是给我们一个指点的点和角度,我们需要绕着过该点的轴线將对象旋转对应的角度。这里我们只改变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编程逐步深入(七)旋转变换的更多相关文章

  1. 《OpenGL编程指南第七版》学习——编译时提示“error C2381: “exit” : 重定义;__declspec(noreturn) 不同”错误的解决办法

    解决办法一. #if defined(_WIN32) # ifndef GLUT_BUILDING_LIBextern _CRTIMP void __cdecl exit(int); 上面是glut. ...

  2. opengl编程指南 第七版 源代码bug Page35 lines.c 红宝书

    问题1:根据源代码时,我发现的时候去敲门.不正确实施效果.哪里是不正确?没有源代码glPushAttrib(GL_LINE_STIPPLE) glPopAttrib().所以会出现最后的下一次抽奖提供 ...

  3. OpenGL编程指南(第七版)

    OpenGL编程指南(第七版) 转自:http://blog.csdn.net/w540982016044/article/details/21287645 在接触OpenGL中,配置显得相当麻烦,特 ...

  4. 编译opengl编程指南第八版示例代码通过

    最近在编译opengl编程指南第八版的示例代码,如下 #include <iostream> #include "vgl.h" #include "LoadS ...

  5. C#编程总结(七)数据加密——附源码

    C#编程总结(七)数据加密——附源码 概述 数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容 ...

  6. 在 Mac OS X Yosemite 10.10.5 上配置 OpenGL 编程环境

    这个教程主要参考了youtube上的视频 Getting Started in OpenGL with GLFW/GLEW in Xcode 6 ,这个视频有点问题,不能照搬.本人通过自己摸(瞎)索( ...

  7. 用MFC实现OpenGL编程

    一.OpenGL简介 众所周知,OpenGL原先是Silicon Graphics Incorporated(SGI公司)在他们的图形工作站上开发高质量图像的接口.但最近几年它成为一个非常优秀的开放式 ...

  8. cesium编程入门(七)3D Tiles,模型旋转

    cesium编程入门(七)3D Tiles,模型旋转 上一节介绍了3D Tiles模型的位置移动,和贴地的操作,这一节来聊一聊模型的旋转, 参考<WebGl编程指南>的第四章 假设在X轴和 ...

  9. 解读经典《C#高级编程》第七版 Page79-93.对象和类型.Chapter3

    前言 本篇我们继续讲解本章其余的部分:构造函数.只读字段.匿名类型.结构详解.部分类.静态类.Object类.扩展方法,等. 01 类 构造函数 构造函数是一种特殊的方法: 与类同名 没有返回值,甚至 ...

  10. 解读经典《C#高级编程》第七版 Page68-79.对象和类型.Chapter3

    前言 新年好,本篇开始进入第三章,<对象和类型>,深刻理解C#的对象,对于使用好.Net类库非常重要. 01 类和结构 从使用角度看,结构和类的区别很小,比如,将结构定义转换为类,只需要将 ...

随机推荐

  1. hdu1290

    由二维的切割问题可知,平面切割与线之间的交点有关,即交点决定射线和线段的条数,从而决定新增的区域数. 当有n-1个平面时,切割的空间数为f(n-1).要有最多的空间数.则第n个平面需与前n-1个平面相 ...

  2. java中StringBuilder、StringBuffer、String类之间的关系

    今天在CSDN的高校俱乐部里看到了"Java基础水平測试(英文)".感觉自己学了java这么久,想看下自己的java水平究竟是个什么样.測试结果就不说了,反正是慘不忍睹. 看了一下 ...

  3. Xshell dns tunnel攻击

    该域名还会向多个超长域名做渗出,且域名采用了 DGA 生成算法,通过 DNS 解析时渗出数据. 部分生成域名如下: sajajlyoogrmkjlkmosbxowcrmwlvajdkbtbjoylyp ...

  4. 前后端分离跨域 关于前后端分离开发环境下的跨域访问问题(angular proxy=>nginx )

    前后端分离后遇到了跨域访问的问题: angular1中使用proxy很麻烦,最后还是失败结束:最后总结3种方法如下: 本人使用的第一种方法,只是开发环境下使用很方便! 1:禁掉谷歌的安全策略(Turn ...

  5. 88.NODE.JS加密模块CRYPTO常用方法介绍

    转自:https://www.jb51.net/article/50668.htm 使用require('crypto')调用加密模块. 加密模块需要底层系统提供OpenSSL的支持.它提供了一种安全 ...

  6. Codeforces 703D Mishka and Interesting sum 离线+树状数组

    链接 Codeforces 703D Mishka and Interesting sum 题意 求区间内数字出现次数为偶数的数的异或和 思路 区间内直接异或的话得到的是出现次数为奇数的异或和,要得到 ...

  7. 《剑指offer》数组中出现次数超过一半的数字

    一.题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出 ...

  8. 51nod1073-约瑟夫环,递归。

    N个人坐成一个圆环(编号为1 - N),从第1个人开始报数,数到K的人出列,后面的人重新从1开始报数.问最后剩下的人的编号. 例如:N = 3,K = 2.2号先出列,然后是1号,最后剩下的是3号. ...

  9. 3ds Max怎么制作亮木材质的球体

    3DSMax怎么制作亮木材质的球体?3DSMax中想要设计一款亮木材质的球体,该怎么设置呢?下面我们就来看看详细的教程,需要的朋友可以参考下! 1.运行软件,选择材质编辑器图标: 3.双击拖拽出的材质 ...

  10. Python3基础笔记---线程与进程

    参考博客:Py西游攻关之多线程(threading模块) 一.并发与并行的区别 并发:交替做不同事的能力并行:同时做不同事的能力 行话解释:并发:不同代码块交替执行的性能并行:不同代码块同时执行的性能 ...