OpenGL学习——入门篇 第三章 四个变换及模拟地球公转

一、四个变换

1.1 视图变换:不同位置观察它;

涉及函数:

glMatrixMode(GL_MODELVIEW);//设置当前操作的矩阵为“模型视图矩阵”
glLoadIdentity();//将当前矩阵设置为单位矩阵

glTranslate* //将当前矩阵和一个表示移动物体的矩阵相乘,三个参数分别表示了在三个坐标上的位置值
实例:

void glTranslated(GLdouble x, GLdouble y, GLdouble z)
void glTranslatef(GLfloat x, GLfloat y, GLfloat z)

glRotate* //把当前矩阵和一个表示旋转物体的矩阵相乘。物体将绕着(0,0,0)到(x,y,z)的直线以逆时针旋转,参数angle表示旋转的角度。
实例:

void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)

glScale*,把当前矩阵和一个表示缩放物体的矩阵相乘。x,y,z分别表示在该方向上的缩放比例。
实例:

void glScalef(GLfloat x,  GLfloat y, GLfloat z);
void glScalex(GLfixed x,  GLfixed y, GLfixed z);

1.2 模型变换:移动、旋转物体,放大缩小物体;

1.3 投影变换:近大远小的透视效果,只看到物体的部分,而非全部(裁剪);

OpenGL支持两种类型的投影变换,即透视投影和正投影.投影也是使用矩阵来实现的。如果需要操作投影矩阵,需要以GL_PROJECTION为参数调用glMatrixMode函数。
glMatrixMode(GL_PROJECTION);
通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。
glLoadIdentity();//同视图变换中的操作
设置当前可是空间为透视投影空间的两种方法
方法一:
glFrustum函数可以将当前的可视空间设置为透视投影空间

void glFrustum(GLdouble left, GLdouble Right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
//创建一个透视型的视景体。其操作是创建一个透视投影的矩阵,并且用这个矩阵乘以当前矩阵。这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的离视点的距离值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。near和far表示离视点的远近,它们总为正值(near/far 必须>0)。

方法二:
gluPerspective函数

void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear, GLdouble zFar)
//创建一个对称的透视型视景体,但它的参数定义于前面的不同,如图。其操作是创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵。参数fovy定义视野在Y-Z平面的角度,范围是[0.0, 180.0];参数aspect是投影平面宽度与高度的比率;参数Near和Far分别是近远裁剪面到视点(沿Z负轴)的距离,它们总为正值。

  以上两个函数缺省时,视点都在原点,视线沿Z轴指向负方向。

方法三:
正投影相当于在无限远处观察得到的结果,它只是一种理想状态。但对于计算机来说,使用正投影有可能获得更好的运行速度。
使用glOrtho函数可以将当前的可视空间设置为正投影空间。

glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far) 
//六个参数, 前两个是x轴最小坐标和最大坐标,中间两个是y轴,最后两个是z轴值;它创建一个平行视景体(就是一个长方体空间区域)。

如果绘制的图形空间本身就是二维的,可以使用gluOrtho2D。他的使用类似于glOrgho。
Reference:
这个博客很不错,不过也是转载的,说的比较清楚
http://blog.csdn.net/peng6662001/article/details/7082436

1.4 视口变换:将整个看到的图形画下来,而非全部;

整个理解的不是很好,后面随着学习的深入,会写上自己的理解

二、使用实例

2.1 先搭个画图的框架

#include "Sun_Earth_Moon.h"
#include <gl/glut.h>
#include <gl/gl.h>
#include <iostream>
#include<windows.h>  
#include<math.h>  
static int day = 200;
static GLfloat angle = 0.0f;
void myDisplay()
{   
    glEnable(GL_DEPTH_TEST); //启动深度测试 
    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清空深度缓冲和颜色缓冲 
    glColor3f(1.0f, 0.0f, 0.0f);
    glutWireSphere(0.5, 50, 50);
    //glutSolidSphere(0.5, 50, 50);
    //glutWireTeapot(0.3);
    glutSwapBuffers();
}

int main(int argv, char* argc[])
{
    glutInit(&argv, argc);
    glutInitDisplayMode(GLUT_RGBA| GLUT_DOUBLE);
    glutInitWindowPosition(400, 400);
    glutInitWindowSize(400, 400);
    glutCreateWindow("study");
    glutDisplayFunc(&myDisplay);
    //glutIdleFunc(&play);
    //glutDisplayFunc(teepot);
    glutMainLoop();
    return 0;
}

我们关注以下几个要点:
第一,如果想要使用glutSwapBuffers(), 我们必须将glutInitDisplayMode中添加属性GLUT_DOUBLE,否则画出来的内容是白色;
第二,Sphere和Teapot的效果图如下:

glutWireSphere(0.5, 50, 50);

wire sphere

glutSolidSphere(0.5, 50, 50);

SolidSphere

glutWireTeapot(0.3);

WireTeapot

glutSolidTeapot(0.3);

SolidTeapot

茶壶和球是我们常用的几个物体,这里就简单介绍到这里,下面我们进入正题,画一个地球围绕太阳进行旋转的图;

2.2 老公围绕媳妇儿转(公转)

下面我这只单身汪将会写一个地球围绕太阳转的实例:

#include "Sun_Earth_Moon.h"
#include <gl/glut.h>
#include <gl/gl.h>
#include<windows.h>  
#include<math.h>  
static int day = 200;
void myDisplay()
{   
    glEnable(GL_DEPTH_TEST); //启动深度测试 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清空深度缓冲和颜色缓冲

    glMatrixMode(GL_PROJECTION);//操作投影矩阵
    glLoadIdentity(); //把当前矩阵设置为单位矩阵  
    gluPerspective(75, 1, 1, 400); //设置可视空间,得到透视效果(可视角,高宽比,最近可视距离,最远可视距离)  

    glMatrixMode(GL_MODELVIEW); //设置当前操作的矩阵为“模型视图矩阵”  
    glLoadIdentity(); //把当前矩阵设置为单位矩阵  
    gluLookAt(0, -200, 200, 0, 0, 0, 0, 0, 1); //设定观察点位置(观察点位置,目标位置,观察者上方向) 

    glColor3f(1.0f, 0.0f, 0.0f);
    glutSolidSphere(50, 50, 50);

    //下面画地球
    glColor3f(0.0f, 0.0f, 1.0f);
    glRotatef(day, 0.0f, 0.0f, -1.0f);
    glTranslatef(150, 0.0f, 0.0f);
    glutSolidSphere(20, 50, 50);

    //下面画月球
    glColor3f(1.0f, 1.0f, 0.0f);
    glRotatef(day / 30.0*360.0 - day, 0.0f, 0.0f, -1.0f);
    glTranslatef(50, 0.0f, 0.0f);
    glutSolidSphere(10, 50, 50);

    glutSwapBuffers();
    //glFinish();
}

void play()
{
    day++;
    if (day >= 360)
        day = 0;
    myDisplay();
    Sleep(10);
    glutPostRedisplay();
}

int main(int argv, char* argc[])
{
    glutInit(&argv, argc);
    glutInitDisplayMode(GLUT_RGBA| GLUT_DOUBLE);
    glutInitWindowPosition(400, 400);
    glutInitWindowSize(400, 400);
    glutCreateWindow("study");
    glutDisplayFunc(play);
    glutMainLoop();
    return 0;
}
程序比较简单,
http://blog.csdn.net/slience_perseverance/article/details/8096233 中对应的第24个例子之所以运行出来的结果是一片空白,是因为glutInitDisplayMode中采用了GLUT_SINGLE,而我们使用了glutSwapBuffers函数,因此需要设置为GLUT_DOUBLE。

实际上太阳没有这么大,因为日地距离较远,基本上这一张图看到的就是俩点,一个太阳,一个地球的点儿,所以这里夸张了一下。效果图如下:

rotate

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值