#define GLUT_DISABLE_ATEXIT_HACK
#include <math.h>
#include "gl/glut.h"
#pragma comment(lib, "glut32.lib")
#define GL_PI 3.1415f
#define RADIUS 50.0f
#define SIZE 100.0f
GLboolean bDepth=false;
GLboolean bOutline=false;
GLfloat fVers[8][3];
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 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;
}
//计算各顶点坐标
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 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(); //强制显示刷新
}
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;
}
OpenGL: 平面图元构造三维实体
最新推荐文章于 2023-10-05 10:26:50 发布