### 实验知识点解析
#### 一、实验背景与目标
本次实验主要针对计算机图形学中的OpenGL库进行深入学习。OpenGL是一种广泛使用的跨语言、跨平台的应用程序编程接口(API),用于渲染2D、3D矢量图形。本实验旨在让学生通过实践操作掌握OpenGL的基本功能,并能够运用这些知识来创建简单的动画。
**实验目标包括:**
1. **掌握OpenGL的闲置函数(idle function)**:了解如何使用闲置函数来更新场景中的动态元素。
2. **掌握OpenGL的时间函数(timer function)**:学会利用时间函数控制动画的播放速度或定时触发某些事件。
3. **掌握OpenGL的简单动画功能**:能够创建基本的动画效果,如旋转图形。
4. **理解OpenGL裁剪窗口、视区、显示窗口的概念及它们之间的关系**:熟悉这些概念对于正确设置视图和控制图形输出至关重要。
5. **进一步掌握OpenGL基本图元的绘制**:包括但不限于点、线、多边形等基本图形的绘制方法。
#### 二、实验内容解析
##### 1. 闲置函数的使用与简单动画
**1.1 旋转的六边形**
**实验内容:**
- 使用OpenGL绘制一个旋转的六边形,如实验图2-1所示。
- 分析并运行旋转的六边形样本程序,观察旋转动画效果。
- 思考如何通过修改闲置函数(`myidle()`)中的旋转角增量(`theta`)来改变旋转速度。
**知识点解析:**
- **闲置函数(`myidle()`)**:在没有用户输入的情况下,此函数会由OpenGL自动调用。可以通过在此函数中更新图形状态来实现动画效果。
- **旋转角增量(`theta`)**:控制图形旋转的速度。增加`theta`的值会使图形旋转得更快,反之则更慢。
- **OpenGL坐标系**:OpenGL使用笛卡尔坐标系,其中原点位于屏幕左下角,向右为X轴正方向,向上为Y轴正方向。
- **三角函数**:通过`cos()`和`sin()`计算出每个顶点的位置,从而实现六边形的旋转。
**示例代码:**
```c++
void myidle() {
theta += 1.0; // 每次增加的角度
glutPostRedisplay(); // 请求重新绘制
}
```
**1.2 线框六边形**
**实验内容:**
- 在`display()`函数中添加代码,以线框模式绘制六边形。
- 添加线宽设置代码,观察不同线宽的效果。
**知识点解析:**
- **线框模式(`glPolygonMode()`)**:设置绘制多边形的模式为线框模式,可以清晰地看到多边形的轮廓。
- **线宽(`glLineWidth()`)**:设置线条的宽度,可以使图形更加醒目。
**示例代码:**
```c++
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 设置为线框模式
glLineWidth(2.0); // 设置线宽
```
**1.3 在图形中添加文字**
**实验内容:**
- 在六边形图形中添加文字,如“Hello”,然后将其替换为自己的名字拼音或英文名字。
**知识点解析:**
- **`glutBitmapCharacter()`**:使用位图字体在屏幕上绘制字符。
- **字符定位(`glRasterPos2i()`)**:设置绘制字符的起始位置。
**示例代码:**
```c++
glRasterPos2i(3, 2); // 设置起始位置
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'H'); // 绘制字符'H'
```
**1.4 变色技术**
**实验内容:**
- 使六边形的颜色在红色和黄色之间闪烁变换。
**知识点解析:**
- **颜色设置(`glColor3f()`)**:设置当前的绘制颜色。
- **条件判断**:通过判断变量`k`的值来切换颜色。
**示例代码:**
```c++
if (k == l) {
glColor3f(1, 0, 0); // 设置红色
k = 0;
} else {
glColor3f(1, 1, 0); // 设置黄色
k = l;
}
```
**1.5 六边形静止,直线单独旋转**
**实验内容:**
- 修改程序,使得六边形保持静止,而直线绕中心点旋转。
**知识点解析:**
- **图形绘制顺序**:通过调整绘制顺序,可以实现特定的视觉效果,如让直线在六边形之上旋转。
- **直线绘制**:使用`glBegin(GL_LINES)`和`glVertex2f()`来绘制直线。
**示例代码:**
```c++
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();
```
**思考问题:**
- 如果需要直线保持与机器时钟的秒针节拍吻合,应该如何修改?
- 解答:可以在闲置函数(`myidle()`)中使用`Sleep()`函数实现延时,同时根据每秒旋转6度的原则调整旋转角度。
**示例代码:**
```c++
void myidle() {
Sleep(1000); // 延时1秒
theta_line += 6 * PI / 180; // 每秒转过6度
glutPostRedisplay(); // 请求重新绘制
}
```
##### 2. 时间函数的使用与简单动画
**实验内容:**
- 将上一节中的闲置函数替换为时间函数。
**知识点解析:**
- **时间函数(`glutTimerFunc()`)**:允许程序员设置一个回调函数,在指定的时间间隔后被调用。
- **回调函数(`mytime()`)**:接受一个整型参数`t`,表示上一次调用该函数后经过的时间(毫秒)。
**示例代码:**
```c++
void mytime(int t) {
theta += 1.0; // 每次增加的角度
glutPostRedisplay(); // 请求重新绘制
glutTimerFunc(1000, mytime, t); // 每隔1秒再次调用自身
}
```
**总结:**
通过本次实验的学习,不仅能够掌握OpenGL的基本功能,还能深入了解如何通过不同的函数和技巧来创建动态的、交互式的图形应用。这对于后续深入研究计算机图形学领域具有重要意义。