OpenGL实验:绘制彩色五角星

OpenGL实验:绘制彩色五角星

第二次编程作业内容

用配置好的OpenGL环境实现彩色五角星效果,以及把五角星作为3D对象绘制出来,通过按键能够调整角度(用J、K、L三个键分别控制三个互相正交方向上的旋转角度)。效果图如下:
五角星


作为一个OpenGL编程新手,对许多函数的用法不是很熟悉,这次编程练习主要熟练了对颜色的配置和3D变换的基础知识。

1.初始化函数

(1)Void glutInit(int*argc,char**argv)//初始化函数库

参数:
- Argc:一个指针,指向从main()函数传递过来的没更改的argc变量。

(2)Void glutInitWindowPositon(int x,int y)//设置窗口位置

参数:
- X: 距离屏幕左边的像素数。-1是默认值,意思就是由窗口管理程序决定窗口出现在哪里。如果不使用默认值,那你就自己设置一个值。
- Y:距离屏幕上边的像素数。和X一样。

(3)Void glutInitWindowSize(int width,int height)//设置初始窗口的大小

参数:
- Width:窗口的宽度。
- Height:窗口的高度。

(4)Void glutInitDisplayMode(unsighed int mode)//设置初始显示模式

参数:
Mode――可以指定下列显示模式。

对应宏定义 意义
GLUT_RGB 0x0000 指定RGB颜色模式的窗口
GLUT_RGBA 0x0000 指定RGBA 颜色模式的窗口
GLUT_INDEX 0x0001 指定颜色索引模式的窗口
GLUT_SINGLE 0x0000 指定单缓存窗口
GLUT_DOUBLE 0x0002 指定双缓存窗口
GLUT_ACCUM 0x0004 窗口使用累加缓存
GLUT_ALPHA 0x0008 窗口的颜色分量包含 alpha 值
GLUT_DEPTH 0x0010 窗口使用深度缓存
GLUT_STENCIL 0x0020 窗口使用模板缓存
GLUT_MULTISAMPLE 0x0080 指定支持多样本功能的窗口
GLUT_STEREO 0x0100 指定立体窗口
GLUT_LUMINANCE 0x0200 窗口使用亮度颜色模型

2.消息事件处理

(1)void glutMainLoop(void)

让glut程序进入事件循环。在一个glut程序中最多只能调用一次。一旦调用,会直到程序结束才返回。

(2)glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height))

注册当前窗口的形状变化回调函数。当改变窗口大小时,该窗口的形状改变回调函数将被调用。

(3)glutDisplayFunc(void (GLUTCALLBACK *func)(void))

注册当前窗口的显示回调函数,当一个窗口的图像层需要重新绘制时,GLUT将调用该窗口的的显示回调函数。显示回调函数不带任何参数,它负责整个图像层的绘制。我们的大部分工作将集中在这个函数中。

(4)glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y))

设置鼠标器按键回调函数,当鼠标的左键、右键或中键被按下时触发被注册的函数执行。

(5)glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y))

设置鼠标器移动回调函数,当鼠标发生移动时执行被注册的函数。

(6)glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y))

设置键盘回调函数,当键盘有键被按下是调用所注册的函数。

(7)glutIdleFunc(void (GLUTCALLBACK *func)(void))

设置空闲回调函数,当CPU空闲时调用该函数。


3.其他函数

(1)void glPushMatrix(void)和void glPopMatrix(void)

第一个函数表示将所有矩阵依次压入堆栈中,顶部矩阵是第二个矩阵的备份;压入的矩阵数不能太多,否则出错。第二个函数表示弹出堆栈顶部的矩阵,令原第二个矩阵成为顶部矩阵,接受当前操作,故原顶部矩阵被破坏;当堆栈中仅存一个矩阵时,不能进行弹出操作,否则出错。

  • OpenGL中的modelview矩阵变换是一个马尔科夫过程:上一次的变换结果对本次变换有影响,上次modelview变换后物体在世界坐标系下的位置是本次modelview变换的起点。默认时本次变换和上次变换不独立。
  • OpenGL物体建模实际上是分两步走的。第一步,在世界坐标系的原点位置绘制出该物体;第二步,通过modelview变换矩阵对世界坐标系原点处的物体进行仿射变换,将该物体移动到世界坐标系的目标位置处。
  • 将modelview变换放在glPushMatrix和glPopMatrix之间可以使本次变换和上次变换独立。
  • 凡是使用glPushMatrix()和glPopMatrix()的程序一般可以判定是采用世界坐标系建模。既世界坐标系固定,modelview矩阵移动物体。

(2)void glLoadIdentity(void)

OpenGL为我们提供了一个非常简单的恢复初始坐标系的手段,那就是调用glLoadIdentity()命令。该命令是一个无参的无值函数,其功能是用一个4×4的单位矩阵来替换当前矩阵(单位矩阵就是对角线上都是1,,其余元素皆为0的矩阵),实际上就是对当前矩阵进行初始化。将当前点移到了屏幕中心,类似于一个复位操作。

  • X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。
  • OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。
  • 中心左面的坐标值是负值,右面是正值。
  • 移向屏幕顶端是正值,移向屏幕底端是负值。
  • 移入屏幕深处是负值,移出屏幕则是正值。
  • 用单位矩阵替换当前矩阵并不改变当前矩阵模式。

(3)void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); 和 void glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z);

  • angle:为旋转的角度,单位为度。
  • x,y,z:为对应xyz轴的布尔值变量。
  • 如果设置的旋转值(x,y,z的值)为正数,那么旋转的方向是逆时针的,如果旋转值是负数,那么旋转的方向是顺时针的。
  • 按照右手原则,假设:glRotatef(45,1,0,0),想象:从坐标(0,0,0)即原点,引出一条线到(1,0,0),用右手握住这条线。右手大拇指指向(0,0,0)至(1,0,0)的方向才握。另外四个手指的弯曲指向即是物体旋转方向。

(4)void glOrtho(float left,float right,float bottom, float top,int near,int far)

  • left表示视景体左面的坐标,right表示右面的坐标,bottom表示下面的,top表示上面的。

(5)void glColor3f(float x, float y)

在OpenGl中设置颜色,一般可以使用glColor3f()。从函数名字就可以看出,它的参数应该有三个,类型是float型的。另外一点是它的参数值的范围是[0.0,1.0]。一般的,可以将这三个参数值视为颜色的成分。需要注意的是,如果在glBegin()与glEnd()函数之间多次连续调用颜色函数,那么,只会显示出最后一次的颜色。


附代码:

#include<windows.h>
#include<GL/glut.h>
#include<cmath>

const GLfloat R = 0.5f;
const GLfloat Pi = 3.1415926536f;
float zoom = 1.0f;
GLfloat winW = 0.0f;
GLfloat winH = 0.0f;
GLfloat xRot = -35.0f;
GLfloat yRot = 15.0f;

void Render()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glPushMatrix();
    /*glLoadIdentity();*/
    glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    glRotatef(yRot, 0.0f, 1.0f, 0.0f);

    float aa = cos(54.0 / 360.0 * 2 * Pi);
    float bb = aa*tan(36.0 / 360.0 * 2 * Pi);
    float cc = sin(54.0 / 360.0 * 2 * Pi) - bb;

    GLfloat point[2][10] = {};

    for (int i = 0; i<10; i += 2)
    {
        float angle = i * 36;
        point[0][i] = (R*cos(angle / 360.0*2.0*Pi) - 0.5);
        point[1][i] = (R*sin(angle / 360.0*2.0*Pi) + 0.5);
        point[0][i + 1] = (cc*R*cos((angle + 36) / 360.0*2.0*Pi) - 0.5);
        point[1][i + 1] = (cc*R*sin((angle + 36) / 360.0*2.0*Pi) + 0.5);
    }

    //确定每个点的颜色
    GLfloat Color[3][10] = { 0 };

    for (int i = 0; i < 10; i++)
    {
        if (i <= 1 || i >= 8) Color[0][i] = 1;    // 0 1 8 9 
        if (i >= 0 && i <= 5) Color[1][i] = 1;     // 0 1 2 3 4 5
        if (i >= 4 && i <= 9) Color[2][i] = 1;    // 4 5 6 7 8 9
    }


    //五角星绘制
    glBegin(GL_TRIANGLE_FAN); //开始绘制
    {
        glColor3f(1, 1, 1);
        glVertex2f(-0.5, 0.5); //中心点
        for (int i = 0; i < 10; i++)
        {
            glColor3f(Color[0][i], Color[1][i], Color[2][i]);//选择颜色
            glVertex2f(point[0][i], point[1][i]);//顶点
        }
        glColor3f(Color[0][0], Color[1][0], Color[2][0]);
        glVertex2f(point[0][0], point[1][0]);//最后一个点要重画


    }
    glEnd();
    glPopMatrix();
    glFlush();
}

void OnReshape(int w, int h)
{
    GLfloat aspectRatio = (GLfloat)w / (GLfloat)h;
    winW = w;
    winH = h;
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();//
    if (w <= h)
    {
        glOrtho(-3.0f*zoom, 3.0f*zoom, -3.0f*zoom / aspectRatio, 3.0f*zoom / aspectRatio, -10.0f*zoom, 10.0f*zoom);
    }
    else {
        glOrtho(-3.0f*zoom*aspectRatio, 3.0f*zoom*aspectRatio, -3.0f*zoom, 3.0f*zoom, -10.0f*zoom, 10.0f*zoom);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void OnMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        xRot += 1;
        yRot += 1;
        glutPostRedisplay();
    }
    else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
    {
        xRot -= 1;
        yRot -= 1;
        glutPostRedisplay();
    }
}

void OnKeyUpDown(int key, int x, int y)
{
    if (key == GLUT_KEY_UP) {
        zoom -= 0.1;
    }
    else if (key == GLUT_KEY_DOWN) {
        zoom += 0.1;

    }
    OnReshape(winW, winH);
    glutPostRedisplay();
}

int main(int argc, char *argv[])

{

    glutInit(&argc, argv);  //对GLUT进行初始化
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式,RGB 单缓存&多缓存
    glutInitWindowPosition(100, 100); //窗口在屏幕中的位置
    glutInitWindowSize(400, 400);//窗口的大小
    glutCreateWindow("Birdy's OpenGL");//创建窗口

    glutDisplayFunc(&Render);
    glutReshapeFunc(OnReshape);
    glutMouseFunc(OnMouse);
    glutSpecialFunc(OnKeyUpDown);

    glutMainLoop();//循环

    return 0;

}

猜你喜欢

转载自blog.csdn.net/ance_xiaojia/article/details/78437969
今日推荐