实验2—OpenGL的简单动画

在这里插入图片描述

一、实验目的

1、了解和掌握OpenGL的闲置函数。
2、掌握OpenGL的时间函数。
3.掌握OpenGL的简单动画功能。
4、了解OpenGL裁剪窗口、视区、显示窗口的概念和它们之间的关系。
5、进一步掌握OpenGL基本图元的绘制。

二、实验内容

1、闲置函数的使用与简单动画。
1)旋转的六边形如实验图2-1所示。
在这里插入图片描述
阅读6.3.3节中旋转的六边形样本程序,分析程序的实现步骤。运行该程序,观察旋转动画效果。
思考:如果要调整旋转速度,旋转更快或更慢,应该如何修改程序?
答:修改旋转角增量,即通过更改myidle()闲置函数的属性值theta大小实现
2)线框六边形。

在display函数中,添加多边形模式设置语句观看效果。
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //线框模式
glLineWidth(2.0);//设置线宽
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//填充模式

运行结果:
在这里插入图片描述
3)在图形中添加字符“Hello”,观察结果,然后将“Hello”字符改为自己名字的拼音或英文字母。
提示:在图形中添加如下代码

glColor3f(1,0,0); 									//设置红色绘图颜色
glRasterPos2i(3,2); 								//定位当前光标,起始字符位置
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'H');	//写字符"H"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'e')	;	//写字符"e"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'l')	;	//写字符"l"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'l')	;	//写字符"l"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'o');	//写字符"o"

运行结果:
在这里插入图片描述
将“Hello”字符改为自己名字的拼音或英文字母
代码修改:

glColor3f(0, 0, 0);  //设置红色绘制颜色
glRasterPos2i(3, 2);    //定位当前光标,起始字符位置
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'X');  //写字符"X"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'X');  //写字符"Y"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'X');   //写字符"M"

在这里插入图片描述
4)变色技术举例
在程序头部设置全部变量:
int k=0;
在myidle函数中添加代码:

if (k==l)
{	glColor3f (1,0,0);
k=0;
}
else
{
glColor3f(1,1,0); 
k=l;
}

然后在绘制函数中屏蔽原来的绘制颜色, 运行查看效果。
答:观察到旋转的六边形图案颜色红黄闪烁。如下图截取到的图:
在这里插入图片描述
在这里插入图片描述
5)六边形静止,直线单独旋转,如实验图2-2所示。
修改前面的程序,使得六边形保持静止, 以六边形中心为起点画一条不同颜色的直线, 终点为六边形某一顶点,使得直线不停绕中心 点旋转。代码保存下来备用。
代码修改:

void Display(void){
    glClear(GL_COLOR_BUFFER_BIT);                       //清屏
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);			//填充模式
    glColor3f(1.0, 1.0, 0);                             //设置黄色绘图颜色
    glBegin(GL_POLYGON);                                //开始绘制六边形 
        for (int i = 0; i < n; i++)
            glVertex2f( R * cos(theta + i * 2 * PI / n), R * sin(theta + i * 2 * PI / n));  //顶点坐标 
            glEnd();
    glBegin(GL_LINES);                                //开始绘制直线 
            glColor3f(1.0, 1.0, 1.0);
            glVertex2f(0.0, 0.0);                   //旋转点坐标 
            glVertex2f(R * cos(theta_line + 2 * PI / n), R * sin(theta_line + 2 * PI / n));  
            glEnd();
    glutSwapBuffers();              //双缓存的刷新模式
}

在这里插入图片描述
思考:如果需要直线保持与机器时钟的秒针节拍吻合,应该如何修改?
提示:可使用Sleep函数,如Sleep(1000)表示延时1秒,放在myidle函数中。
答:要直线保持与机器时钟的秒针节拍吻合,可在myidle函数中设置Sleep(1000)延时1秒,并设置theta += 6*PI/180,使得每秒转过6°,一分钟转一周。
2.时间函数的使用与简单动画。将以上程序中的闲置函数替换为时间函数。
1 )主程序中:
glutldleFunc(myidle) ; //注册闲置回调函数
改为:
glutTimerFunc(1000, mytime, 10) ; //1000 毫秒后调用时间函数 mytime
2 )myidle()闲置回调函数改为时间函数mytime(t),在程序顶部函数声明语句也要相应更改:
void myidle();
改为:
void mytime(int t);
3)在时间函数mytime(t)最后再添加:
glutTimerFunc(1000, mytime, 10) ; //1000 毫秒后调用时间函数 mytime
3、简单时钟的设计。

  1. 在程序头部定义系统时间变量、时分秒变量:
    SYSTEMTIME timeNow;
    float hh,mm,ss;
    2)在程序头部定义7T常量:
    #define PI 3.1415926
    3)在程序头部引入数学头文件、时间头文件:
    #include"math.h"
    #include"time.h"
    4)在初始化函数中获取系统时间。在主程序中顶部声明初始化子函数:
    void init ();
    在main函数中添加子函数调用语句,可放在创建窗口之后:
    void init ()
    { GetLocalTime(&timeNow); hh=timeNow.wHour; mm=timeNow.wMinute; ss=timeNow.wSecond;
    }
    5)在绘制函数中计算时、分、秒,确定绘制时分秒针起始点坐标,例如:
//xc, yc为时针中心点坐标
//xs, ys为秒针终止点坐标
//xm, ym为分针终止点坐标
xs=xc+R*cos(PI/2.0-ss/60*2*PI);
ys=yc+R*sin(PI/2.0-ss/60*2*PI);
xm=xc+R*cos(PI/2.0-(mm+ss/60.0)/60.0*2.0*PI);
ym=yc+R*sin(PI/2.0-(mm+ss/60.0)/60.0*2.0*PI);
xh=xc+(R-5)*cos(PI/2.0-(hh+(mm+ss/60.0)/60.0)/12.0*2.0*PI);
yh=yc+(R-5)*sin(PI/2.0-(hh+(mm+ss/60.0)/60.0)/12.0*2.0*PI);

6)在绘制函数中以直线方式简易绘制时、分、秒针:

glColor3f(1,0,0); 
glBegin(GL_LINES); 
glVertex2f(xc,yc); 
glVertex2f(xs,ys); 
glEnd();
glColor3f(1,1,0); 
glBegin(GL_LINES); 
glVertex2f(xc,yc);
glVertex2f(xm,ym); 
glEnd();
glColor3f(0,l,1)glBegin(GL_LINES);
glVertex2f(xc,yc);
glVertex2f(xh,yh);
glEnd ()

7)闲置函数中或时间函数中重复获取系统时间:

GetLocalTime(&timeNow); //获取系统时间 
hh=timeNow.wHour; 		//获取小时时间 
mm=timeNow.wMinute; 	//获取分钟时间 
ss=timeNow.wSecond; 	//获取秒时间
最终实验代码:
#include "stdafx.h"
#include <gl/glut.h>
#include <math.h>
#include"time.h"
#define MAX_LOADSTRING 100
#define PI 3.14159
SYSTEMTIME timeNow;
float hh,mm,ss;
int n=6,R=10;
int k=0;
// 此代码模块中包含的函数的前向声明:
float theta=0.0;
float theta_line=0.0;
void Keyboard(unsigned char key, int x,int y);
void Display(void);
void Reshape(int w,int h);
void mytime(int t);
void init();
int main(int argc,char* argv[])
{
    glutInit(&argc, argv); //初始化GTD工座
    glutInitWindowSize(700,700);//设置显示窗口大小
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); // 设置显示模式 (注意双缓存)
    glutCreateWindow("A Rotating Square"); // 创建显示窗口
    init();
    glutDisplayFunc(Display); // 注册显示回调函数
    glutReshapeFunc(Reshape); //注册窗口改变回调函数
    glutTimerFunc(1000,mytime,10); //1000毫秒后调用时间函数mytime
    glutMainLoop(); //进入事件处理循环
    return 0;
}
void Display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    glLineWidth(2.0);
    glColor3f(1, 0, 0);
    glBegin(GL_POLYGON);
	for (int i = 0; i < n; i++) { //绘制正六边形
		glVertex2f(R*cos(theta + i * 2 * PI / n), R*sin(theta + i * 2 * PI / n));
}
    glEnd();
	//xc,yc为时针中心点坐标
	//xs,ys为秒针终止点坐标
	//xm,ym为分针终止点坐标
	float xs, ys, xm, ym, xh, yh;
	float xc = 0, yc = 0;
	//Calculate
	xs = xc + R * cos(PI / 2.0 - ss / 60 * 2 * PI);
	ys = yc + R * sin(PI / 2.0 - ss / 60 * 2 * PI);
	xm = xc + R * cos(PI / 2.0 - (mm + ss / 60.0) / 60.0*2.0*PI);
	ym = yc + R * sin(PI / 2.0 - (mm + ss / 60.0) / 60.0*2.0*PI);
	xh = xc + (R - 5)*cos(PI / 2.0 - (hh + (mm + ss / 60.0) / 60.0) / 12.0*2.0*PI);
    yh = yc + (R - 5)*sin(PI / 2.0 - (hh + (mm + ss / 60.0) / 60.0) / 12.0*2.0*PI);
	glColor3f(1, 0, 0);
	glBegin(GL_LINES);
	glVertex2f(xc, yc);
	glVertex2f(xs, ys);
	glEnd();
	glColor3f(1, 1, 0);
	glBegin(GL_LINES);
	glVertex2f(xc, yc);
	glVertex2f(xm, ym);
	glEnd();
	glColor3f(0, 1, 1);
	glBegin(GL_LINES);
	glVertex2f(xc, yc);
	glVertex2f(xh, yh);
	glEnd();
	glutSwapBuffers();//双缓存的刷新模式
}
void mytime(int t)
{
	GetLocalTime(&timeNow);
	hh = timeNow.wHour;
	mm = timeNow.wMinute;
	ss = timeNow.wSecond;
    glutPostRedisplay(); //重画,相当于重新调用Display(),改变后的变量得以传给绘制函数
    glutTimerFunc(1000, mytime,10);
}
void Reshape(GLsizei w,GLsizei h)
{
     glMatrixMode(GL_PROJECTION); //投影矩阵模式
     glLoadIdentity(); //矩阵堆栈清空
     gluOrtho2D(-1.5*R*w/h,1.5*R*w/h,-1.5*R,1.5*R);//设置裁剪窗口大小
     glViewport(0,0,w,h);// 设置视区大小
     glMatrixMode(GL_MODELVIEW); //模型矩阵模式
}
void init()
{
    GetLocalTime(&timeNow);// 获取系统时间
    hh=timeNow.wHour;//获取小时时间
    mm=timeNow.wMinute;//获取分钟时间
    ss=timeNow.wSecond;//获取秒时间
}

实验结果:
在这里插入图片描述

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实验OpenGL+GLUT开发平台搭建 5 小实验1: 开发环境设置 5 小实验2: 控制窗口位置和大小 6 小实验3:默认的可视化范围 6 小实验4:自定义可视化范围 7 小实验5: 几何对象变形的原因 8 小实验6: 视口坐标系及视口定义 8 小实验7:动态调整长宽比例,保证几何对象不变形 9 实验动画和交互 10 小实验1: 单缓冲动画技术 10 小实验2: 双缓冲动画技术 11 小实验3:键盘控制 13 小实验4:鼠标控制【试着单击鼠标左键或者右键,试着按下鼠标左键后再移动】 14 实验三 几何变换、观察变换、三维对象 16 小实验1:二维几何变换 16 小实验2:建模观察(MODELVIEW)矩阵堆栈 17 小实验3:正平行投影1 19 小实验4:正平行投影2 19 小实验5:正平行投影3 20 小实验6:透射投影1 21 小实验6:透射投影2 22 小实验7:三维对象 24 实验四 光照模型和纹理映射 26 小实验1:光照模型1----OpenGL简单光照效果的关键步骤。 26 小实验2:光照模型2----光源位置的问题 28 小实验3:光照模型3----光源位置的问题 31 小实验4:光照模型4----光源位置的问题 33 小实验5:光照模型5----光源位置的问题 35 小实验6:光照模型6----光源位置的问题 38 小实验7:光照模型7----光源位置的动态变化 40 小实验8:光照模型8----光源位置的动态变化 43 小实验9:光照模型9---光源位置的动态变化 45 小实验10:光照模型10---聚光灯效果模拟 48 小实验11:光照模型11---多光源效果模拟 50 小实验12:光照效果和雾效果的结合 53 小实验13:纹理映射初步—掌握OpenGL纹理映射的一般步骤 56 小实验13:纹理映射—纹理坐标的自动生成(基于参数的曲面映射) 59 小实验14:纹理映射—纹理坐标的自动生成(基于参考面距离) 61

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊hii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值