参考书籍:OpenGL编程基础-第三版
大多数的曲线都将由若干直线段来逼近表示,而曲面也将由一系列多边形来逼近表示。所以首先我们来将一个三角形离散化。
画三角形函数:
在OpenGL中,逆时针方向画图的方向为正面
void triangle(GLfloat *a, GLfloat *b, GLfloat *c)
{
glBegin(GL_TRIANGLES);
glVertex2fv(a);
glVertex2fv(b);
glVertex2fv(c);
glEnd();
}
细分函数
将每条边的中点互相连接,可以在一个三角形中得到四个小三角形
//从一个三角形开始递归地细分n次
void divide_triangle(GLfloat * a, GLfloat * b, GLfloat * c, int m)
{
GLfloat v[3][2]; //存储每条边的中点
int j;
if(m>0)
{
//计算各个边中点的坐标
for(j = 0;j < 2 ;j++)
v[0][j] = (a[j] + b[j]) /2;
for(j = 0;j < 2 ;j++)
v[1][j] = (a[j] + c[j]) /2;
for(j = 0;j < 2 ;j++)
v[2][j] = (c[j] + b[j]) /2;
divide_triangle(a, v[0], v[1], m-1);
divide_triangle(v[0], b, v[2], m-1);
divide_triangle(v[1], v[2], c, m-1);
divide_triangle(v[0], v[2], v[1], m-1);
}
else
triangle(a, b, c);
}
主函数+显示回调函数+状态初始化函数
#include<GL/glut.h>
//事件回调函数
void triangle(GLfloat *, GLfloat *, GLfloat *);//绘制一个三角形
void divide_triangle(GLfloat *, GLfloat *, GLfloat *, int );//从一个三角形开始递归地细分n次
void display(void)
{
GLfloat v[3][2] = { -0.5, -0.5, 0.5, -0.5, 0, 0.5};
glClear(GL_COLOR_BUFFER_BIT); //清除颜色缓存
divide_triangle(v[0], v[1],v[2],2);
glFlush();
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);//设置清屏颜色为黑色
//由函数glClearColor设置的颜色必须指定为RGBA颜色,A指的是透明度,而且每个分量的类型必须是GLclampf
glColor3f(1.0, 1.0, 1.0);//设置绘制颜色为白色
glMatrixMode(GL_PROJECTION); //指定投影矩阵会收到后续变换函数的影响
glLoadIdentity();//将当前矩阵初始化为单位矩阵
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
//背面和正面都应该设置为非填充图元,画线的时候顺时针为背面
glPolygonMode(GL_FRONT, GL_LINE);
}
int main(int argc, char ** argv)
{
glutInit(&argc,argv); //初始化GLUT,应在其他GLUT和OpenGL函数之前进行调用
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//指定窗口类型,RGB颜色和单缓存
glutInitWindowSize(500,500);//指定窗口大小
glutInitWindowPosition(0,0);//指定窗口左上角相对于屏幕左上角的位置
glutCreateWindow("simple"); //创建窗口并命名为"simple"
glutDisplayFunc(display); //指定回调函数
init();
glutMainLoop(); //使程序进入无限事件处理循环,该函数的调用应作为main函数最后一条语句出现
}
细分两次的运行结果: