计算机图形学第二次上机——旋转的三角形

计算机图形学第二次上机实验 课程实验报告

写在前面:这是我的图形学上机报告,代码都是自己写的,实测通过,查阅了许多资料,现以链接的形式给出

glut初始化

glutSpecialFunc响应键盘方向控制键

glutBitmapCharacter函数实现字符显示

glutPostRedisplay函数

若遇到其他问题,希望大家多动手多查资料,不要蒙混过关,这样才能有收获。

最后希望这份报告能够帮到大家~

目录

计算机图形学第二次上机实验 课程实验报告

一、实验目的

二、实验环境

三、实验内容

1.立方体放缩变换

2.对称变换

3.键盘回调函数实现三角形旋转

四、实验心得

五、源代码


一、实验目的

  1. 掌握配置glut库的步骤
  2. 测试运行示例代码
  3. 掌握并编写中点线算法和中点圆算法

二、实验环境

1.codeblocks-17.12

2.Windows10 SDK 10.0.17134.0

三、实验内容

1.立方体放缩变换

问题重述:利用OpenGL实现一个立方体关于参考点(10.0,20.0,10.0)进行放缩变换,放缩因子为(2.0,1.0,0.5)。

为了使放缩效果更佳,我将整个图形进行了旋转,又由于矩阵堆栈是先进先出的,故变换代码框架为:

glRotatef(45,1,1,1);//绕着向量(1,1,1)所指定的轴旋转45°

glPushMatrix();//保存矩阵状态

glTranslatef(10,20,10);//从原点平移到原处,T2

    glPushMatrix();

    glScalef(2,1,0.5);//放缩变换,S

    glPushMatrix();

    glTranslatef(-10,-20,-10);//从当前平移至原点,T1

    glPushMatrix();

    glColor3f(1.0,0.0,0.0);

glutWireCube(10.0);

运行效果:

变换前

变换后

2.对称变换

问题重述:利用OpenGL实现一个矩形关于y=x+5对称的新图形。

变换的关键就是先通过平移将对称轴经过原点,再旋转与坐标轴平行。进行对称变换,然后再变换回去。

主要变换代码如下

 glTranslatef(0,5,0);//T2,y平移5个单位

glPushMatrix();

glRotated(45,0,0,1);//R2,逆时针旋转45度

glPushMatrix();

glScaled(1,-1,1);//S,放缩变换

glPushMatrix();

glRotated(-45,0,0,1);//R1 逆顺时针旋转45度,与x轴重合

glPushMatrix();

glTranslated(0,-5,0);//T1 y平移-5个单位

glPushMatrix();

glColor3f(1,0,0);

glRectf(-5,10,0,50);//x1=T2*R2*S*R1*T1*x

注意矩阵堆栈是先进先出即可。

运行结果为

3.键盘回调函数实现三角形旋转

问题重述:通过定义键盘回调函数,每按一次空格键,让三个点依次完成画点、画线、画三角形、让三角形平移和缩放,并让三角形沿三角形中心旋转起来。

问题的关键在于注册回调函数以及如何使三角形旋转,由于问题较为复杂,我将分段说明。

3.1定义全局变量以及模式

需要使用的全局变量为

int currentMode = 0;//当前模式数

int enable=0;//是否旋转

int angle = 0;   //当前旋转角度

int step = 1;  //每次的角度递增值

const int ModeNums = 7;//模式总数

窗口回调函数RenderScene定义各个模式为

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

switch(currentMode)

{

case 0:

                displayc();//画点

        glPointSize(4);

glBegin(GL_POINTS);

    glColor3f(0,1.0,0.0);

break;

case 1:displayc();//画开折线

                glBegin(GL_LINE_STRIP);

    glColor3f(1.0,0,0.0);

    break;

case 2: displayc();//画闭折线

                glBegin(GL_LINE_LOOP);

    glColor3f(0.0,0.0,1.0);

break;

case 3: displayc();//画填充三角形

                glBegin(GL_TRIANGLES);

    glColor3f(1.0,0,1.0);

break;

        case 4:displayc();//平移

                glMatrixMode(GL_MODELVIEW);

                glLoadIdentity();

                glTranslated(2,2,0);

                glBegin(GL_TRIANGLES);

                glColor3f(0,0,0);

                break;

        case 5:displayc();//放缩

                glMatrixMode(GL_MODELVIEW);

                glLoadIdentity();

                glScaled(1.5,1.5,1);

                glBegin(GL_TRIANGLES);

                glColor3f(1,0,0);

                break;

        case 6:

                Rotate();//旋转

                break;

}

glVertex2f( -6.0, -3.0 );

glVertex2f( 4.0, -4.0 );

glVertex2f( 2.0, 7.0 );

glEnd();

glFlush();

glutSwapBuffers();

glLoadIdentity();

    if(enable==1)

        glutPostRedisplay();

}

一共有7个模式。

3.2键盘回调函数

对于字符值键盘回调函数,可以用

glutKeyboardFunc(myKey);  //为当前窗口设置键盘回调函数。

进行注册,其实现为:

void myKey( unsigned char key, int x, int y)

//响应ASCII对应键,鼠标的当前x和y位置也被返回。

{

switch(key)

{

case ' ': currentMode = (currentMode+1)%ModeNums;

      glutPostRedisplay();

  break;

        case 'r':enable=1;

                  glutPostRedisplay();

  break;

        case 's':enable=0;

                  glutPostRedisplay();

                  break;

case 27:  exit(-1);

}

}

对于上下左右特殊按键的键盘回调函数,可以用

glutSpecialFunc(SpecialKey);

进行注册,其实现为:

void SpecialKey(int key,int x,int y)

{

    switch(key)

    {

        case GLUT_KEY_UP:

            step++;

            break;

        case GLUT_KEY_DOWN:

            step--;

            break;

    }

}

3.3实现三角形的旋转

3.3.1初始化双缓冲区

之前我没有注意到自己仅仅使用了单缓冲区,导致动画效果很差,后来详细查找了一下glutInitDisplayMode函数的参数列表:

函数原型void glutInitDisplayMode(unsigned int mode),函数功能为设置初始显示模式。

函数功能:设置初始显示模式。

函数原型:void glutInitDisplayMode(unsigned int mode);

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

窗口使用亮度颜色模型

用“或“(|)操作符来建立想要的显示模式

想要流畅地显示动画,必须设置双缓冲区,而且我使用了RGB色彩空间,于是初始化语句为

glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

3.3.2.通过不断地刷新并交换缓冲区实现旋转

1.当使能信号enable=1时可以旋转,于是先定义矩阵堆栈模式glMatrixMode(GL_MODELVIEW);

glLoadIdentity();//矩阵堆栈可以保存上次旋转结果

2.压入旋转角度angle+=step的旋转矩阵(我定义的三个点的中心刚好在原点,所以不需要计算旋转中心,默认原点就好)

    angle=(angle+step)%360;

glRotated(angle,0,0,1);

3.画填充三角形并刷新画面和交换缓冲区

 glBegin(GL_TRIANGLES);

glColor3f(1,0,0);

glVertex2f( -6.0, -3.0 );

glVertex2f( 4.0, -4.0 );

glVertex2f( 2.0, 7.0 );

glEnd();

glFlush();

glutSwapBuffers();//交换缓冲区保证有流畅动画

4.当使能信号enable=1时重复上述过程,实现旋转

  if(enable==1)

        glutPostRedisplay();

最后一种模式case=6时旋转,相应的窗口回调函数代码段为

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

switch(currentMode)

{……

case 6:

                Rotate();//旋转

                break;

}

glVertex2f( -6.0, -3.0 );

glVertex2f( 4.0, -4.0 );

glVertex2f( 2.0, 7.0 );

glEnd();

glFlush();

glutSwapBuffers();

glLoadIdentity();

    if(enable==1)

        glutPostRedisplay();

}

Rotate函数实现为:

void Rotate()

{

//显示提示字符

……

//旋转

glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    angle=(angle+step)%360;

    glRotated(angle,0,0,1);

    glBegin(GL_TRIANGLES);

    glColor3f(1,0,0);

}

3.4实现文字提示

Glut内置了字符提示函数

glRasterPos2d(double x,double y)

定义了光标位置,其中坐标为世界坐标,即(0,0)为世界坐标中心。

glutBitmapCharacter(font , character)

定义了字体和要显示的字符,仅限ASC||表中的字符,参数范围如下

font

设置字符的字体,选择范围如下:

GLUT_BITMAP_8_BY_13

GLUT_BITMAP_9_BY_15

GLUT_BITMAP_TIMES_ROMAN_10 字体:TIMES_ROMAN 大小:10

GLUT_BITMAP_TIMES_ROMAN_24 字体:TIMES_ROMAN 大小:24

GLUT_BITMAP_HELVETICA_10

GLUT_BITMAP_HELVETICA_12

GLUT_BITMAP_HELVETICA_18

character

要显示的字符。

我用以上两个内置函数实现了字符提示函数displayc

void displayc()

{

    glColor3f(0, 0, 0);

    char str[]="Press space to continue,press escape to exit!";

    glClear(GL_COLOR_BUFFER_BIT);

    glRasterPos2d(-39.5,20);

    for(int i=0;i<sizeof(str);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str[i]);

    }

    glFlush();

}

以及Rotate函数中显示字符的代码段

//显示提示字符

    char str[]="Press 'R' to Rotate,'S' to stop";

    glClear(GL_COLOR_BUFFER_BIT);

    glRasterPos2d(-25,20);

    for(int i=0;i<sizeof(str);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str[i]);

    }

    char str1[]="Press Up to Speed up,Down to Slow down";

    glRasterPos2d(-30,15);

    for(int i=0;i<sizeof(str1);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str1[i]);

    }

运行结果

1.画点

2.画开折线

3.画闭折线

4.画填充三角形

5.平移

6.放缩

7.旋转

四、实验心得

此次实验我查阅了大量资料,终于在详细了解了许多OpenGL函数之后实现了一个简单的动画以及键盘回调函数,在最后代码运行无误,画面能正确响应键盘的时候内心还是很开心的。

五、源代码

1.立方体放缩

#include"windows.h"

#ifndef GLUT_DISABLE_ATEXIT_HACK

#define GLUT_DISABLE_ATEXIT_HACK

#endif

#include <glut.h>

void init()

{

glClearColor(1.0,1.0,1.0,1.0);

}

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

    glRotatef(45,1,1,1);//绕着向量(1,1,1)所指定的轴旋转45°

glPushMatrix();//保存矩阵状态

glTranslatef(10,20,10);//从原点平移到原处,T2

    glPushMatrix();

    glScalef(2,1,0.5);//放缩变换,S

    glPushMatrix();

    glTranslatef(-10,-20,-10);//从当前平移至原点,T1

    glPushMatrix();

    glColor3f(1.0,0.0,0.0);

glutWireCube(10.0);

    //glFlush();

glLoadIdentity();

glRotatef(45,1,1,1);//绕着向量(1,1,1)所指定的轴旋转45°

    //画x坐标轴

glBegin(GL_LINES);

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(40,0,0);

glEnd();

//画y坐标轴

glBegin(GL_LINES);

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(0,40,0);

glEnd();

//画z坐标轴

glBegin(GL_LINES);

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(0,0,40);

glEnd();

glFlush();

}

void ChangeSize(GLsizei w,GLsizei h)

{

GLfloat aspectRatio;

if(h==0)

h = 1;

glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

aspectRatio = (GLfloat)w/(GLfloat)h;

if(w<=h)

glOrtho(-50.0,50.0,-50.0/aspectRatio,50.0/aspectRatio,-50.0,50.0);

else

glOrtho(-50.0*aspectRatio,50.0*aspectRatio,-50.0,50.0,-50.0,50.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

int main()

{

glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);

glutCreateWindow("Scale_Cube");

init();

glutDisplayFunc(RenderScene);

glutReshapeFunc(ChangeSize);

glutMainLoop();

return 0;

}

2.旋转变换

#include<windows.h>

#include <GL/glut.h>

void init()

{

glClearColor(1.0,1.0,1.0,0.0);

}

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glColor3f(0,0,0.5);

glRectf(-5,10,0,50);

//原矩阵

glBegin(GL_LINES);

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(80,0,0);

glEnd();

//x轴

glBegin(GL_LINES);

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(0,80,0);

glEnd();

//y轴

glBegin(GL_LINES);

glColor3f(0,1,0);

glVertex3f(-50,-45,0);

glVertex3f(50,55,0);

glEnd();

glTranslatef(0,5,0);//T2,y平移5个单位

glPushMatrix();

glRotated(45,0,0,1);//R2,逆时针旋转45度

glPushMatrix();

glScaled(1,-1,1);//S,放缩变换

glPushMatrix();

glRotated(-45,0,0,1);//R1 逆顺时针旋转45度,与x轴重合

glPushMatrix();

glTranslated(0,-5,0);//T1 y平移-5个单位

    glPushMatrix();

glColor3f(1,0,0);

glRectf(-5,10,0,50);//x1=T2*R2*S*R1*T1*x

glFlush();

}

void ChangeSize(GLsizei w,GLsizei h)

{

float ratio;

if(h==0)

h = 1;

ratio = (GLfloat)w/(GLfloat)h;

glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if(w<=h)

gluOrtho2D(-100.0,100.0,-100.0/ratio,100.0/ratio);

else

gluOrtho2D(-100.0*ratio,100.0*ratio,-100.0,100);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

int main()

{

glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);

glutInitWindowPosition(400,300);

glutInitWindowSize(300,300);

glutCreateWindow("Geometric transformation 2");

init();

glutDisplayFunc(RenderScene);

glutReshapeFunc(ChangeSize);

glutMainLoop();

return 0;

}

3.旋转三角形

#include"windows.h"

#include <stdlib.h>

#include <stdio.h>

#include <glut.h>

#include<gl.h>

#include <stdlib.h>

#include <string>

int currentMode = 0;

int enable=0;//是否旋转

int angle = 0;   //当前旋转角度

int step = 1;  //每次的角度递增值

const int ModeNums = 7;

typedef struct  {

float x,y;

}point;

void Rotate();

void init()

{

glClearColor(1.0,1.0,1.0,1.0);

}

void myKey( unsigned char key, int x, int y) //响应ASCII对应键,鼠标的当前x和y位置也被返回。

{

switch(key)

{

case ' ': currentMode = (currentMode+1)%ModeNums;

      glutPostRedisplay();

  break;

        case 'r':enable=1;

                  glutPostRedisplay();

  break;

        case 's':enable=0;

                  glutPostRedisplay();

                  break;

case 27:  exit(-1);

}

}

void SpecialKey(int key,int x,int y)

{

    switch(key)

    {

        case GLUT_KEY_UP:

            step++;

            break;

        case GLUT_KEY_DOWN:

            step--;

            break;

    }

}

void displayc()

{

    glColor3f(0, 0, 0);

    char str[]="Press space to continue,press escape to exit!";

    glClear(GL_COLOR_BUFFER_BIT);

    glRasterPos2d(-39.5,20);

    for(int i=0;i<sizeof(str);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str[i]);

    }

    glFlush();

}

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

switch(currentMode)

{

case 0:

                displayc();//画点

        glPointSize(4);

glBegin(GL_POINTS);

    glColor3f(0,1.0,0.0);

break;

case 1:displayc();//画开折线

                glBegin(GL_LINE_STRIP);

    glColor3f(1.0,0,0.0);

    break;

case 2: displayc();//画闭折线

                glBegin(GL_LINE_LOOP);

    glColor3f(0.0,0.0,1.0);

break;

case 3: displayc();//画填充三角形

                glBegin(GL_TRIANGLES);

    glColor3f(1.0,0,1.0);

break;

        case 4:displayc();//平移

                glMatrixMode(GL_MODELVIEW);

                glLoadIdentity();

                glTranslated(2,2,0);

                glBegin(GL_TRIANGLES);

                glColor3f(0,0,0);

                break;

        case 5:displayc();//放缩

                glMatrixMode(GL_MODELVIEW);

                glLoadIdentity();

                glScaled(1.5,1.5,1);

                glBegin(GL_TRIANGLES);

                glColor3f(1,0,0);

                break;

        case 6:

                Rotate();//旋转

                break;

}

glVertex2f( -6.0, -3.0 );

glVertex2f( 4.0, -4.0 );

glVertex2f( 2.0, 7.0 );

glEnd();

glFlush();

glutSwapBuffers();//交换缓冲区保证有流畅动画

glLoadIdentity();

    if(enable==1)

        glutPostRedisplay();

}

void Rotate()

{

    glColor3f(0, 0, 0);//设置黑色绘制颜色

    

    //显示提示字符

    char str[]="Press 'R' to Rotate,'S' to stop";

    glClear(GL_COLOR_BUFFER_BIT);

    glRasterPos2d(-25,20);

    for(int i=0;i<sizeof(str);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str[i]);

    }

    char str1[]="Press Up to Speed up,Down to Slow down";

    glRasterPos2d(-30,15);

    for(int i=0;i<sizeof(str1);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str1[i]);

    }

    //旋转

glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    angle=(angle+step)%360;

    glRotated(angle,0,0,1);

    glBegin(GL_TRIANGLES);

    glColor3f(1,0,0);

}

void ChangeSize(GLsizei w,GLsizei h)

{

float ratio;

if(h==0)

h = 1;

glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

ratio = (float)w/(float)h;

//gluOrtho2D(-10.0,10.0,-10.0,10.0);

if(w<=h)

gluOrtho2D(-40.0,40.0,-40.0/ratio,40.0/ratio);

else

gluOrtho2D(-40.0*ratio,40.0*ratio,-40.0,40.0);

glMatrixMode(GL_MODELVIEW);

}

int main()

{

glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

glutInitWindowPosition(50,50);

glutInitWindowSize(360,360);

glutCreateWindow("KeyboardFunc");

init();

glutDisplayFunc(RenderScene);

glutReshapeFunc(ChangeSize);

glutKeyboardFunc(myKey);  //为当前窗口设置键盘回调函数。

    glutSpecialFunc(SpecialKey);

printf("Press space to continue,press escape to exit!\n");

glutMainLoop();

return 0;

}

发布了47 篇原创文章 · 获赞 28 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_41122796/article/details/84193653
今日推荐