一、初始化
先写函数ChangeSize对窗口初始化,然后根据展示效果写不同的绘图函数。此处用OpenGL库与MFC工程结合,调用glut库中已有的glutWireTeapot、glutWireSphere等方法直接绘图。
void ChangeSize(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
glMatrixMode(GL_MODELVIEW);
}
二、线框图
(1)茶壶线框图
主函数void CMFCApplication2View::On32797(),绘制茶壶的线框图函数void RenderScene(void)。
1、代码如下:
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 1.0f, 1.0f);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glScalef(1.0f, 2.0f, 1.0f);
glutWireTeapot(1.0);
glutSwapBuffers();
}
//茶壶线框图
void CMFCApplication2View::On32797()
{
// TODO: 在此添加命令处理程序代码
glutInit(&__argc, __argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(w, h); //窗口大小
glutInitWindowPosition(100, 100);
glutCreateWindow("瘦茶壶线框图");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
glutMainLoop();
}
2、效果如下:
(2)球体线框图
主函数void CMFCApplication2View::On32798(),绘制球体的线框图函数void RenderScene1(void),在此通过调整glut库里的glutWireSphere参数,将线框球体压扁,展示出一个蜘蛛网的效果。
1、代码如下:
void RenderScene1(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 1.0f, 1.0f);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glScalef(1.0f, 2.0f, 1.0f);
glutWireSphere(1,10,10);
glutSwapBuffers();
}
//球体线框图
void CMFCApplication2View::On32798()
{
// TODO: 在此添加命令处理程序代码
glutInit(&__argc, __argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(w, h); //窗口大小
glutInitWindowPosition(100, 100);
glutCreateWindow("蜘蛛网线框图");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene1);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
glutMainLoop();
}
2、效果如下:
二、实体图
茶壶实体图:主函数void CMFCApplication2View::On32799(),绘制茶壶的实体图函数void RenderScene21(void)。
1、代码如下:
void RenderScene21(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 1.0f, 1.0f);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glScalef(1.0f, 2.0f, 1.0f);
glutSolidTeapot(1.0);
glutSwapBuffers();
}
//茶壶实体图
void CMFCApplication2View::On32799()
{
// TODO: 在此添加命令处理程序代码
glutInit(&__argc, __argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(w, h); //窗口大小
glutInitWindowPosition(100, 100);
glutCreateWindow("茶壶实体图");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene21);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
glutMainLoop();
}
2、效果如下:
三、场景图
1、代码如下:
//OpenGL场景图 上下左右移动
//根据八个点绘制长方体
void constract(double x, double y, double z, double x1, double y1, double z1)
{
eigh[0][0] = x;
eigh[0][1] = y;
eigh[0][2] = z; // 第0个点
eigh[1][0] = x;
eigh[1][1] = y;
eigh[1][2] = z + z1; // 第一个点
eigh[2][0] = x + x1;
eigh[2][1] = y;
eigh[2][2] = z + z1; // 第二个点
eigh[3][0] = x + x1;
eigh[3][1] = y;
eigh[3][2] = z; // 第三个点
for (int i = 0; i < 4; i++) // for()循环来完成其余的四个点
{
for (int j = 0; j < 3; j++)
{
if (j == 1)
eigh[i + 4][j] = eigh[i][j] + y1;
else
eigh[i + 4][j] = eigh[i][j];
}
}
}
//根据六个顶点绘制三棱柱
void cons(double x, double y, double z, double x1, double y1, double z1, double length)
{
thre[0][0] = x;
thre[0][1] = y;
thre[0][2] = z; //第一个点,三角形底边的一个点
thre[1][0] = x1;
thre[1][1] = y1;
thre[1][2] = z1; //第二个点,三角形上面的那个点
int hemiZ = z - z1;
int Z = 2 * hemiZ;
thre[2][0] = x;
thre[2][1] = y;
thre[2][2] = z - Z; //第三个点,三角形底边的另外一个点
for (int i = 3; i < 6; i++)
{
thre[i][0] = thre[i - 3][0] + length;
thre[i][1] = thre[i - 3][1];
thre[i][2] = thre[i - 3][2];
}
//点的顺序:0左侧-底面-前 1左侧-顶点 2左侧-底面-后 3右侧-底面-前 4右侧-顶点 5右侧-底面-后
}
//建造矩形
void build()
{
glBegin(GL_POLYGON);
glNormal3f(0.0, -1.0, 0.0);
glVertex3f(eigh[0][0], eigh[0][1], eigh[0][2]);
glVertex3f(eigh[1][0], eigh[1][1], eigh[1][2]);
glVertex3f(eigh[2][0], eigh[2][1], eigh[2][2]);
glVertex3f(eigh[3][0], eigh[3][1], eigh[3][2]);
glEnd(); // 下底
glBegin(GL_POLYGON);
glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(eigh[1][0], eigh[1][1], eigh[1][2]);
glVertex3f(eigh[0][0], eigh[0][1], eigh[0][2]);
glVertex3f(eigh[4][0], eigh[4][1], eigh[4][2]);
glVertex3f(eigh[5][0], eigh[5][1], eigh[5][2]);
glEnd(); // 左面
glBegin(GL_POLYGON);
glNormal3f(1.0, 0.0, 0.0);
glVertex3f(eigh[7][0], eigh[7][1], eigh[7][2]);
glVertex3f(eigh[6][0], eigh[6][1], eigh[6][2]);
glVertex3f(eigh[2][0], eigh[2][1], eigh[2][2]);
glVertex3f(eigh[3][0], eigh[3][1], eigh[3][2]);
glEnd(); // 右面
glBegin(GL_POLYGON);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(eigh[5][0], eigh[5][1], eigh[5][2]);
glVertex3f(eigh[6][0], eigh[6][1], eigh[6][2]);
glVertex3f(eigh[2][0], eigh[2][1], eigh[2][2]);
glVertex3f(eigh[1][0], eigh[1][1], eigh[1][2]);
glEnd(); // 前面
glBegin(GL_POLYGON);
glNormal3f(0.0, 0.0, -1.0);
glVertex3f(eigh[0][0], eigh[0][1], eigh[0][2]);
glVertex3f(eigh[3][0], eigh[3][1], eigh[3][2]);
glVertex3f(eigh[7][0], eigh[7][1], eigh[7][2]);
glVertex3f(eigh[4][0], eigh[4][1], eigh[4][2]);
glEnd(); // 后面
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(eigh[4][0], eigh[4][1], eigh[4][2]);
glVertex3f(eigh[7][0], eigh[7][1], eigh[7][2]);
glVertex3f(eigh[6][0], eigh[6][1], eigh[6][2]);
glVertex3f(eigh[5][0], eigh[5][1], eigh[5][2]);
glEnd(); // 上面
}
//建造一个三棱柱,用于画房顶
void build2()
{
//画左侧的三角形
glBegin(GL_TRIANGLES);
glVertex3f(thre[0][0], thre[0][1], thre[0][2]);
glVertex3f(thre[1][0], thre[1][1], thre[1][2]);
glVertex3f(thre[2][0], thre[2][1], thre[2][2]);
glEnd();
//画右侧的三角形
glBegin(GL_TRIANGLES);
glVertex3f(thre[3][0], thre[3][1], thre[3][2]);
glVertex3f(thre[4][0], thre[4][1], thre[4][2]);
glVertex3f(thre[5][0], thre[5][1], thre[5][2]);
glEnd();
//画前面的四边形
glBegin(GL_POLYGON);
//glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(thre[0][0], thre[0][1], thre[0][2]);
glVertex3f(thre[3][0], thre[3][1], thre[3][2]);
glVertex3f(thre[4][0], thre[4][1], thre[4][2]);
glVertex3f(thre[1][0], thre[1][1], thre[1][2]);
glEnd();
//画后面的四边形
glBegin(GL_POLYGON);
//glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(thre[2][0], thre[2][1], thre[4][2]);
glVertex3f(thre[1][0], thre[1][1], thre[1][2]);
glVertex3f(thre[4][0], thre[4][1], thre[4][2]);
glVertex3f(thre[5][0], thre[5][1], thre[4][2]);
glEnd();
//画底层的四边形
glBegin(GL_POLYGON);
//glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(thre[2][0], thre[2][1], thre[2][2]);
glVertex3f(thre[0][0], thre[0][1], thre[0][2]);
glVertex3f(thre[3][0], thre[3][1], thre[3][2]);
glVertex3f(thre[5][0], thre[5][1], thre[5][2]);
glEnd();
}
//开始绘制三维场景
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); //增加M矩阵
glRotatef(rotate_x, 1.0, 0.0, 0.0);
glRotatef(rotate_y, 0.0, 1.0, 0.0);
glTranslatef(-270, 0, -270);
glScalef(1.5, 1.5, 1.5);
//constract第三个参数小了往里跑,第四个参数越小越窄,
// 第五个参数小了top高度低了,第六个参数向外边长
//地面底板(浅粉色)
glBegin(GL_POLYGON);
constract(-200, 0, 0, 700, 10, 500);
glColor3f(slightpink);
build();
//墙壁(颜色为淡黄色)
glColor3f(yellow);
constract(50, 10, 100, 12, 160, 212); //左墙壁
build();
constract(388, 10, 100, 12, 160, 212); //右墙壁
build();
constract(62, 10, 100, 336, 160, 12); //后墙壁
build();
constract(62, 10, 300, 336, 160, 12); //前墙壁
build();
//房顶(颜色红色)
glColor3f(red);
cons(35, 170 + 0.1, 327, 35, 250 + 0.1, 206, 380);
build2();
//画矩形条 烟囱
glColor3f(coffee);
constract(80, 190, 110, 30, 120, 12);
build();
//太阳
glColor3f(gold);
glTranslatef(-90, 380, 0);
glutSolidSphere(35.0, 20, 20);
glTranslatef(-250, -350, 0);
//门(门为蓝色,门把手为咖色)
glColor3f(lightblue);
constract(545, -20, 310, 50, 70, 6); //门
build();
glColor3f(coffee);
constract(580, -5, 312, 10, 20, 8); //门把手
build();
//左窗户蓝色,添加透明度
glColor4f(lightblue, 0.35);
constract(430, 120, 312, 80, -80, 4);
build();
//右窗户蓝色,添加透明度
glColor4f(lightblue, 0.35);
constract(625, 120, 312, 80, -80, 4);
build();
//小路(颜色brown)
for (int i = 340; i < 500; i += 45)
{
glColor3f(brown);
constract(545, -20, i, 50, 2, 20);
build();
}
// 第一组
//1树干
glColor3f(coffee);
constract(165, -20, 390, 20, 50, 20);
build();
//1树叶
glColor3f(deepgreen);
glTranslatef(165, 50, 400);
glutSolidSphere(25.0, 20, 20); //球1左
glTranslatef(20, 0, 0);
glutSolidSphere(25.0, 20, 20); //球2右
glTranslatef(-10, 0, -10);
glutSolidSphere(25.0, 20, 20); //球3后
glTranslatef(0, 0, 20);
glutSolidSphere(25.0, 20, 20); //球4前
glTranslatef(0, 10, -10);
glutSolidSphere(25.0, 20, 20); //球5上
glTranslatef(100, -80, -400);
//2树干
glColor3f(coffee);
constract(-50, 0, 390, 20, 50, 20);
build();
//2树叶
glColor3f(deepgreen);
glTranslatef(-50, 50, 400);
glutSolidSphere(25.0, 20, 20); //球1左
glTranslatef(20, 0, 0);
glutSolidSphere(25.0, 20, 20); //球2右
glTranslatef(-10, 0, -10);
glutSolidSphere(25.0, 20, 20); //球3后
glTranslatef(0, 0, 20);
glutSolidSphere(25.0, 20, 20); //球4前
glTranslatef(0, 10, -10);
glutSolidSphere(25.0, 20, 20); //球5上
glTranslatef(100, -80, -400);
//3树干
glColor3f(coffee);
constract(-40, 20, 390, 20, 60, 20);
build();
//3树叶
glColor3f(deepgreen);
glTranslatef(-40, 60, 400);
glutSolidSphere(25.0, 20, 20); //球1左
glTranslatef(20, 0, 0);
glutSolidSphere(25.0, 20, 20); //球2右
glTranslatef(-10, 0, -10);
glutSolidSphere(25.0, 20, 20); //球3后
glTranslatef(0, 0, 20);
glutSolidSphere(25.0, 20, 20); //球4前
glTranslatef(0, 10, -10);
glutSolidSphere(25.0, 20, 20); //球5上
glTranslatef(100, -80, -400);
// 第二组
//1树干
glColor3f(coffee);
constract(-240, 30, 280, 20, 70, 20);
build();
glColor3f(deepgreen);
glTranslatef(-240, 110, 290);
glutSolidSphere(25.0, 20, 20); //球1左
glTranslatef(20, 0, 0);
glutSolidSphere(25.0, 20, 20); //球2右
glTranslatef(-10, 0, -10);
glutSolidSphere(25.0, 20, 20); //球3后
glTranslatef(0, 0, 20);
glutSolidSphere(25.0, 20, 20); //球4前
glTranslatef(0, 10, -10);
glutSolidSphere(25.0, 20, 20); //球5上
glTranslatef(100, -80, -400);
//2树干
glColor3f(coffee);
constract(-45, -10, 375, 20, 50, 20);
build();
glColor3f(deepgreen);
glTranslatef(-45, 40, 385);
glutSolidSphere(25.0, 20, 20); //球1左
glTranslatef(20, 0, 0);
glutSolidSphere(25.0, 20, 20); //球2右
glTranslatef(-10, 0, -10);
glutSolidSphere(25.0, 20, 20); //球3后
glTranslatef(0, 0, 20);
glutSolidSphere(25.0, 20, 20); //球4前
glTranslatef(0, 10, -10);
glutSolidSphere(25.0, 20, 20); //球5上
glTranslatef(100, -80, -400);
//3树干
glColor3f(coffee);
constract(-20, 20, 390, 20, 30, 20);
build();
//3树干
glColor3f(deepgreen);
glTranslatef(-20, 60, 400);
glutSolidSphere(25.0, 20, 20); //球1左
glTranslatef(20, 0, 0);
glutSolidSphere(25.0, 20, 20); //球2右
glTranslatef(-10, 0, -10);
glutSolidSphere(25.0, 20, 20); //球3后
glTranslatef(0, 0, 20);
glutSolidSphere(25.0, 20, 20); //球4前
glTranslatef(0, 10, -10);
glutSolidSphere(25.0, 20, 20); //球5上
glTranslatef(100, -80, -400);
// 第三组
//1树
glColor3f(coffee);
constract(-260, 30, 310, 20, 70, 20);
build();
glColor3f(deepgreen);
glTranslatef(-260, 110, 320);
glutSolidSphere(25.0, 20, 20); //球1左
glTranslatef(20, 0, 0);
glutSolidSphere(25.0, 20, 20); //球2右
glTranslatef(-10, 0, -10);
glutSolidSphere(25.0, 20, 20); //球3后
glTranslatef(0, 0, 20);
glutSolidSphere(25.0, 20, 20); //球4前
glTranslatef(0, 10, -10);
glutSolidSphere(25.0, 20, 20); //球5上
glTranslatef(100, -80, -400);
//2树
glColor3f(coffee);
constract(-55, -10, 375, 20, 50, 20);
build();
glColor3f(deepgreen);
glTranslatef(-55, 40, 385);
glutSolidSphere(25.0, 20, 20); //球1左
glTranslatef(20, 0, 0);
glutSolidSphere(25.0, 20, 20); //球2右
glTranslatef(-10, 0, -10);
glutSolidSphere(25.0, 20, 20); //球3后
glTranslatef(0, 0, 20);
glutSolidSphere(25.0, 20, 20); //球4前
glTranslatef(0, 10, -10);
glutSolidSphere(25.0, 20, 20); //球5上
glTranslatef(100, -80, -400);
//3树干
glColor3f(coffee);
constract(-30, 20, 390, 20, 30, 20);
build();
//3树干
glColor3f(deepgreen);
glTranslatef(-30, 60, 400);
glutSolidSphere(25.0, 20, 20); //球1左
glTranslatef(20, 0, 0);
glutSolidSphere(25.0, 20, 20); //球2右
glTranslatef(-10, 0, -10);
glutSolidSphere(25.0, 20, 20); //球3后
glTranslatef(0, 0, 20);
glutSolidSphere(25.0, 20, 20); //球4前
glTranslatef(0, 10, -10);
glutSolidSphere(25.0, 20, 20); //球5上
glTranslatef(100, -80, -400);
glFlush(); // 刷新
glutSwapBuffers();//还要加上swapbuffer函数
}
//窗口初始化
void init2(void)
{
GLfloat sun_direction[] = { 100.0, 100.0, 100.0, 0.0 };
GLfloat sun_intensity[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat ambient_intensity[] = { 0.5, 0.5, 0.5, 1.0 };
glEnable(GL_LIGHTING); // 设置氛围光
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient_intensity);
glEnable(GL_LIGHT0); //设置阳光
glLightfv(GL_LIGHT0, GL_POSITION, sun_direction);
glLightfv(GL_LIGHT0, GL_DIFFUSE, sun_intensity);
glEnable(GL_COLOR_MATERIAL); //打开颜色渲染
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClearColor(0.0, 0.0, 0.0, 0.0); //定义背景颜色为黑色
glEnable(GL_BLEND); // 打开混合
glEnable(GL_DEPTH_TEST);// 关闭深度测试
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // 基于源象素alpha通道值的半透明混合函数
glMatrixMode(GL_PROJECTION); // 定义视角
glOrtho(-w, w, -h, h, -w, w); //创建一个正交平行的视景体
}
//键盘控制函数
void specialkeys(int key, int x, int y)
{
if (key == GLUT_KEY_RIGHT)
rotate_y += 5;
else if (key == GLUT_KEY_LEFT)
rotate_y -= 5;
else if (key == GLUT_KEY_UP)
rotate_x += 5;
else if (key == GLUT_KEY_DOWN)
rotate_x -= 5;
glutPostRedisplay();
}
//三维场景图图像平移、旋转变换,键盘操控
void CMFCApplication2View::On32801()
{
// TODO: 在此添加命令处理程序代码
glutInit(&__argc, __argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(w, h); //窗口大小
glutInitWindowPosition(100, 100);
glutCreateWindow("场景图");
init2();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glutDisplayFunc(display);
glutSpecialFunc(specialkeys);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
glutMainLoop();
}
2、效果如下:
运行后的场景图 键盘操作后的主视图
键盘操作后的左视图 键盘操作后的俯视图
在场景图的绘制中,用到了gl库中的glEnable(GL_LIGHTING)方法来设置氛围光。用到glEnable(GL_COLOR_MATERIAL)方法打开颜色渲染,让我画的图出现色彩。