效果图:


代码:
#define GLUT_DISABLE_ATEXIT_HACK
#include "gl/glut.h"
#include <math.h>
#define GL_PI 3.1415f
#define RADIUS 50.0f
#define SIZE 100.0f
GLboolean bDepth=false;
GLboolean bOutline=false;
GLfloat fVers[8][3];
void OnDisplay(void);
void OnReshape(int,int);
void OnMenu(int value);
void CreatMenu();
void SetupLights();
void CalaulateVertices(GLfloat vers[8][3]);
void CalaulateNormal(GLfloat [3][3],GLfloat *);
void Unitlize(GLfloat *);
int main(int argc, char* argv[])
{
glutInit(&argc,argv); //初始化OpenGL
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); //设置显示模式
glutInitWindowSize(600,480);
glutCreateWindow("利用平面图元构造三维实体");
glutCreateMenu(OnMenu);
glutReshapeFunc(OnReshape);
glutDisplayFunc(OnDisplay);
CreatMenu(); //实际生成菜单(对于windows应用程序,这里的菜单技术是无效的,因为windows有自己的菜单系统)
SetupLights(); //设置光照
CalaulateVertices(fVers); //计算所绘实体各顶点的坐标
glutMainLoop(); //进入OpenGL主循环
return 0;
}
void OnDisplay(void)
{
GLint i;
GLfloat ver[3][3],nor[3];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除颜色和深度缓冲区
if (bDepth)
glEnable(GL_DEPTH_TEST); //启用深度检测
else
glDisable(GL_DEPTH_TEST);//关闭深度检测
if (bOutline)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); //以线框形式进行绘制
else
glPolygonMode(GL_FRONT,GL_FILL); //以实体形式进行绘制
glPushMatrix();
glRotatef(75,1.0f,0.0f,0.0f);
glRotatef(150,0.0f,1.0f,0.0f);
glTranslatef(0.0f,-25.0f,-25.0f);
glFrontFace(GL_CW); //指定多边形成型方式为顺时针
glColor3f(0.0f,1.0f,0.0f);//指定绘图颜色为绿色
glBegin(GL_TRIANGLE_FAN); //利用三角扇形绘制六棱锥的六个侧面
ver[0][0]=fVers[0][0];
ver[0][1]=fVers[0][1];
ver[0][2]=fVers[0][2];
glVertex3f(fVers[0][0],fVers[0][1],fVers[0][2]);
for (i=1;i<8;i++)
{
ver[1][0]=fVers[i][0];
ver[1][1]=fVers[i][1];
ver[1][2]=fVers[i][2];
if(i<=7){
ver[2][0]=fVers[i+1][0];
ver[2][1]=fVers[i+1][1];
ver[2][2]=fVers[i+1][2];
}
else{
ver[2][0]=fVers[1][0];
ver[2][1]=fVers[1][1];
ver[2][2]=fVers[1][2];
}
CalaulateNormal(ver,nor); //计算并归一化法向量
glNormal3fv(nor); //设置法向量
glVertex2f(fVers[i][0],fVers[i][1]);
}
glEnd();
glBegin(GL_TRIANGLE_FAN);//利用三角扇形绘制六棱锥的顶面
glNormal3f(0.0f,0.0f,1.0f);//指定法向量
glVertex2f(fVers[0][0],fVers[0][1]);
for (i=7;i>0;i--)
{
glNormal3f(0.0f,0.0f,1.0f); //指定法向量
glVertex2f(fVers[i][0],fVers[i][1]);
}
glEnd();
glPopMatrix();
glutSwapBuffers(); //交换前后缓冲区(相当于刷新显示)
}
void OnReshape(int w,int h)
{
GLfloat aspect =(GLfloat)w/(GLfloat)h;
GLfloat nRange=100.0f;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影模式
glLoadIdentity();
//设置三维投影区
if (w<=h)
{
glOrtho(-nRange,nRange,-nRange/aspect,nRange/aspect,-nRange,nRange);
}
else
{
glOrtho(-nRange,nRange,-nRange*aspect,nRange*aspect,-nRange,nRange);
}
glMatrixMode(GL_MODELVIEW); //将当前矩阵恢复为模型视图模式
glLoadIdentity();
}
void OnMenu(int value)
{
switch(value){ //当前用户选择的菜单项的ID
case 1:
bDepth=!bDepth;
break;
case 2:
bOutline=!bOutline;
}
glutPostRedisplay(); //强制显示刷新
}
void CreatMenu()
{
glutAddMenuEntry("深度检测",1); //添加菜单项
glutAddMenuEntry("线框或实体",2);
glutAttachMenu(GLUT_RIGHT_BUTTON); //指定菜单事件由右击产生
}
//设置光照
void SetupLights()
{
GLfloat ambientLight[]={0.2f,0.2f,0.2f,1.0f};//环境光
GLfloat diffuseLight[]={0.9f,0.9f,0.9f,1.0f};//漫反射
GLfloat lightPos[]={50.0f,80.0f,60.0f,1.0f};//光源位置
glEnable(GL_LIGHTING); //启用光照
glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);//设置环境光源
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);//设置漫反射光源
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);//设置灯光位置
glEnable(GL_LIGHT0); //打开第一个灯光
glEnable(GL_COLOR_MATERIAL); //启用材质的颜色跟踪
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); //指定材料着色的面
}
//计算各顶点坐标
void CalaulateVertices(GLfloat vers[8][3])
{
GLfloat angle;
GLint i=1;
vers[0][0]=vers[0][1]=0.0f;
vers[0][2]=75.0f;
for (angle=0.0f;angle<2.1f*GL_PI;angle+=GL_PI /3,i++)
{
vers[i][0]=RADIUS*sin(angle);
vers[i][1]=RADIUS*cos(angle);
vers[i][2]=0.0f;
}
}
//计算并归一化法向量
void CalaulateNormal(GLfloat vertices[3][3],GLfloat *normal)
{
GLfloat v1[3],v2[3];
v1[0]=vertices[0][0]=vertices[1][0];
v1[1]=vertices[0][1]=vertices[1][1];
v1[2]=vertices[0][2]=vertices[1][2];
v2[0]=vertices[1][0]=vertices[2][0];
v2[1]=vertices[1][1]=vertices[2][1];
v2[2]=vertices[1][2]=vertices[2][2];
normal[0]=v1[1]*v2[2]-v1[2]*v2[1];
normal[1]=v1[0]*v2[2]-v1[2]*v2[0];
normal[2]=v1[1]*v2[0]-v1[0]*v2[1];
Unitlize(normal);//归一化
}
//归一化法向量
void Unitlize(GLfloat *vertex)
{
GLfloat len=GLfloat(sqrt(vertex[0]*vertex[0]+vertex[1]*vertex[1]+
vertex[2]*vertex[2]));
if (len==0.0f)
len=1.0f;
vertex[0]/=len;
vertex[1]/=len;
vertex[2]/=len;
}
posted on
浙公网安备 33010602011771号