Experiment 2 - Simple animation with OpenGL

insert image description here

1. Purpose of the experiment

1. Understand and master the idle functions of OpenGL.
2. Master the time function of OpenGL.
3. Master the simple animation functions of OpenGL.
4. Understand the concept of OpenGL clipping window, viewport, and display window and the relationship between them.
5. Further master the drawing of the basic primitives of OpenGL.

2. Experimental content

1. The use of idle functions and simple animation.
1) The rotating hexagon is shown in Figure 2-1 of the experiment.
insert image description here
Read the rotating hexagon sample program in Section 6.3.3, and analyze the implementation steps of the program. Run the program and observe the rotation animation effect.
Thinking: If you want to adjust the rotation speed, faster or slower, how should you modify the program?
Answer: Modify the rotation angle increment, that is, realize
2) the wireframe hexagon by changing the attribute value theta size of the myidle() idle function.

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

Running results:
insert image description here
3) Add the character "Hello" to the graphic, observe the result, and then change the character "Hello" to the pinyin or English letters of your own name.
Tip: Add the following code in the graph

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"

Running result:
insert image description here
Change the character "Hello" to the pinyin or English letters of your name
Code modification:

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"

insert image description here
4) Example of color changing technology
Set all variables at the head of the program:
int k=0;
add code in the myidle function:

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

Then mask the original drawing color in the drawing function, and run to see the effect.
Answer: Observe that the color of the rotating hexagon pattern flashes red and yellow. The picture is intercepted in the following picture:
insert image description here
insert image description here
5) The hexagon is stationary, and the straight line rotates independently, as shown in the experimental picture 2-2.
Modify the previous program to keep the hexagon still, draw a straight line with different colors starting from the center of the hexagon, and end at a vertex of the hexagon, so that the straight line keeps rotating around the center point. Save the code for future use.
Code modification:

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();              //双缓存的刷新模式
}

insert image description here
Thinking: If the straight line needs to keep in line with the beat of the second hand of the machine clock, how should it be modified?
Tip: You can use the Sleep function, such as Sleep(1000) means a delay of 1 second, and put it in the myidle function.
Answer: To keep the straight line consistent with the beat of the second hand of the machine clock, you can set Sleep(1000) in the myidle function to delay for 1 second, and set theta += 6*PI/180, so that every second rotates 6°, and one minute rotates a week.
2. The use of time function and simple animation. Replace the idle function in the above program with the time function.
1) In the main program:
glutldleFunc(myidle); //Register the idle callback function
and change it to:
glutTimerFunc(1000, mytime, 10) ; //Call the time function mytime after 1000 milliseconds
2) Myidle() idle callback function is changed to a time function mytime(t), the function statement at the top of the program should be changed accordingly:
void myidle();
changed to:
void mytime(int t);
3) Add at the end of the time function mytime(t):
glutTimerFunc(1000, mytime, 10) ; //Call the time function mytime after 1000 milliseconds
3. Simple clock design.

  1. Define the system time variable and the hour, minute and second variable at the program header:
    SYSTEMTIME timeNow;
    float hh, mm, ss;
    2) Define the 7T constant at the program header:
    #define PI 3.1415926
    3) Introduce the math header file and time header at the program header File:
    #include "math.h"
    #include "time.h"
    4) Obtain the system time in the initialization function. Declare the initialization sub-function at the top of the main program:
    void init ();
    Add a sub-function call statement in the main function, which can be placed after the window is created:
    void init ()
    { GetLocalTime(&timeNow); hh=timeNow.wHour; mm= timeNow.wMinute; ss=timeNow.wSecond;
    }
    5) Calculate the hour, minute, and second in the drawing function, and determine the coordinates of the starting point of the hour, minute, and second hand for drawing, for example:
//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) In the drawing function, simply draw the hour, minute and second hands in a straight line:

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) Obtain the system time repeatedly in the idle function or in the time function:

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;//获取秒时间
}

Experimental results:
insert image description here

Guess you like

Origin blog.csdn.net/weixin_52030647/article/details/130715411