一、说明
就是老师布置的大作业,要求就是设计上课的一些内容,能够完成一个作业,体现作业量。
二、代码
本人记得是参考网上的一些案例改进的,做的并不算好,就是完成一个任务。
#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
#include <iostream>
#define PI 3.14;
static GLfloat MatSpec[] = { 1.0,1.0,1.0,1.0 };
static GLfloat MatShininess[] = { 50.0 };
static GLfloat LightPos[] = { -2.0,1.5,1.0,0.0 };
static GLfloat ModelAmb[] = { 0.5,0.5,0.5,0.0 };
GLint TowerListNum, WallsListNum;
GLint WallsLIst;
//哨塔相关参数
int NumOfEdges = 50;//细分度
GLfloat LowerHeight = 3.0;
GLfloat HigherHeight = 3.5;
GLfloat HR = 1.3;
//城墙相关参数
GLfloat WallElementSize = 0.2;
GLfloat WallHeight = 2.0;
GLfloat angleX = 0.0f;
GLfloat angleY = 0.0f;
int lastMouseX, lastMouseY;
bool rotate = false;
// 物体的当前位置
bool drag = false;
GLfloat scale = 1.0f;
GLfloat objX = 0.0f;
GLfloat objY = 0.0f;
//绘制城墙上方凸起部分
void DrawHigherWallPart(int NumElements)
{
glBegin(GL_QUADS);
for (int i = 0; i < NumElements; i++)
{
glNormal3f(0.0, 0.0, -1.0);
glVertex3f(i*2.0*WallElementSize, 0.0, 0.0);
glVertex3f(i*2.0*WallElementSize, WallElementSize, 0.0);
glVertex3f((i*2.0 + 1.0)*WallElementSize, WallElementSize, 0.0);
glVertex3f((i*2.0 + 1.0)*WallElementSize, 0.0, 0.0);
}
glEnd();
}
//绘制城墙
void DrawWall(GLfloat Length)
{
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, WallHeight, 0.0);
glVertex3f(Length, WallHeight, 0.0);
glVertex3f(Length, 0.0, 0.0);
glEnd();
int i = (int)(Length / WallElementSize / 2);
if (i*WallElementSize > Length)
i--;
glPushMatrix();
glTranslatef(0.0, WallHeight, 0.0);
DrawHigherWallPart(i);
glPopMatrix();
}
//初始化函数,绘制塔哨、城墙
void Init(void)
{
//绘制塔哨
TowerListNum = glGenLists(1);
GLfloat x, z;
GLfloat NVectY;
glNewList(TowerListNum, GL_COMPILE);
glBegin(GL_QUADS);
//创建塔身的圆柱体部分
int i;
for (i = 0; i < NumOfEdges - 1; i++)
{
x = cos((float)i / (float)NumOfEdges*2.0*3.1415265359);
z = sin((float)i / (float)NumOfEdges*2.0*3.1415265359);
glNormal3f(x, 0.0, z);
glVertex3f(x, LowerHeight, z);
glVertex3f(x, 0.0, z);
x = cos((float)(i + 1) / (float)NumOfEdges*2.0*3.1415265359);
z = sin((float)(i + 1) / (float)NumOfEdges*2.0*3.1415265359);
glNormal3f(x, 0.0, z);
//以上述法线方向绘制两个顶点
glVertex3f(x, 0.0, z);
glVertex3f(x, LowerHeight, z);
}
//计算最后一个四边形的前两个点法向量的x,z坐标
x = cos((float)i / (float)NumOfEdges*2.0*3.1415265359);
z = sin((float)i / (float)NumOfEdges*2.0*3.1415265359);
glNormal3f(x, 0.0, z);//设置法向量方向
glVertex3f(x, LowerHeight, z);
glVertex3f(x, 0.0, z);
x = cos(1.0 / (float)NumOfEdges*2.0*3.1415265359);
z = sin(1.0 / (float)NumOfEdges*2.0*3.1415265359);
glNormal3f(x, 0.0, z);
glVertex3f(x, 0.0, z);
glVertex3f(x, LowerHeight, z);
//绘制哨塔上方倒圆台部分
NVectY = (HR - 1.0) / (LowerHeight - HigherHeight)*(HR - 1.0);
for (int i = 0; i < NumOfEdges - 1; i++)
{
x = cos((float)i / (float)NumOfEdges*2.0*3.1415265359);
z = sin((float)i / (float)NumOfEdges*2.0*3.1415265359);
glNormal3f(x, NVectY, z);//设置法向量方向
glVertex3f(x*HR, HigherHeight, z*HR);
glVertex3f(x, LowerHeight, z);
x = cos((float)(i + 1) / (float)NumOfEdges*2.0*3.1415265359);
z = sin((float)(i + 1) / (float)NumOfEdges*2.0*3.1415265359);
glNormal3f(x, NVectY, z);//设置法向量方向
glVertex3f(x, LowerHeight, z);
glVertex3f(x*HR, HigherHeight, z*HR);
}
x = cos((float)i / (float)NumOfEdges*2.0*3.1415265359);
z = sin((float)i / (float)NumOfEdges*2.0*3.1415265359);
glNormal3f(x, NVectY, z);
glVertex3f(x*HR, HigherHeight, z*HR);
glVertex3f(x, LowerHeight, z);
x = cos(1.0 / (float)NumOfEdges*2.0*3.1415265359);
z = sin(1.0 / (float)NumOfEdges*2.0*3.1415265359);
glNormal3f(x, NVectY, z);
glVertex3f(x, LowerHeight, z);
glVertex3f(x*HR, HigherHeight, z*HR);
glEnd();
glEndList();
//绘制城墙和大门
WallsListNum = glGenLists(1);
glNewList(WallsListNum, GL_COMPILE);
DrawWall(10.0);
glPushMatrix();
glTranslatef(10.0, 0.0, 0.0);
glPushMatrix();
glRotatef(270.0, 0.0, 1.0, 0.0);
DrawWall(10.0);
glPopMatrix();
glTranslatef(0.0, 0.0, 10.0);
glPushMatrix();
glRotatef(180.0, 0.0, 1.0, 0.0);
DrawWall(5.0);
glRotatef(90.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, 5.0);
DrawWall(5.0);
glPopMatrix();
glTranslatef(-5.0, 0.0, 5.0);
glPushMatrix();
glRotatef(180.0, 0.0, 1.0, 0.0);
DrawWall(5.0);
glPopMatrix();
glPushMatrix();
glRotatef(90.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -5.0);
DrawWall(6.0);
//绘制前方大门
glTranslatef(6.0, 0.0, 0.0);
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0, -1.0);
//绘制四边形的四个点
glVertex3f(0.0, WallHeight / 2.0, 0.0);
glVertex3f(0.0, WallHeight, 0.0);
glVertex3f(3.0, WallHeight, 0.0);
glVertex3f(3.0, WallHeight / 2, 0.0);
glEnd();
i = (int)(3.0 / WallElementSize / 2);
if (i*WallElementSize > 3.0)
i--;
glPushMatrix();
glTranslatef(0.0, WallHeight, 0.0);
DrawHigherWallPart(i);
glPopMatrix();
glTranslatef(3.0, 0.0, 0.0);
DrawWall(6.0);
glPopMatrix();
glPopMatrix();
glEndList();
}
//绘制函数
void Display(void)
{
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
glTranslatef(-3.0, -3.0, -20.0);
glRotatef(85.0, 0.0, 1.0, 0.0);
glRotatef(15.0, 0.0, 0.0, 1.0);
glRotatef(angleX, 100.0f, 0.0f, 0.0f);
glRotatef(angleY, 0.0f, 100.0f, 0.0f);
glScalef(scale, scale, scale);
glTranslatef(objX, objY, -5.0f);
//绘制地面
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
//绘制7个顶点
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(10.0, 0.0, 0.0);
glVertex3f(10.0, 0.0, 10.0);
glVertex3f(5.0, 0.0, 10.0);
glVertex3f(5.0, 0.0, 15.0);
glVertex3f(0.0, 0.0, 15.0);
glVertex3f(0.0, 0.0, 0.0);
glEnd();
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glCallList(WallsListNum);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
//执行哨塔显示列表绘制第一个哨塔
glCallList(TowerListNum);
glTranslatef(10.0, 0.0, 0.0);
glCallList(TowerListNum);
glTranslatef(0.0, 0.0, 10.0);
glCallList(TowerListNum);
glTranslatef(-5.0, 0.0, 5.0);
glCallList(TowerListNum);
glTranslatef(-5.0, 0.0, 0.0);
glCallList(TowerListNum);
glFlush();
glutSwapBuffers();
}
//窗口改变函数
void Reshape(int x, int y)
{
glViewport(0, 0, x, y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0, (GLdouble)x / (GLdouble)y, 1.0, 200.0);
glMatrixMode(GL_MODELVIEW);
}
void mouse(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
rotate = true;
drag = true;
lastMouseX = x;
lastMouseY = y;
}
else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
rotate = false;
drag = false;
}
if (button == 3) {
scale += 0.1f;
}
else if (button == 4) {
if (scale > 0.1f) {
scale -= 0.1f;
}
}
glutPostRedisplay();
}
void motion(int x, int y) {
if (rotate) {
int deltaX = x - lastMouseX;
int deltaY = y - lastMouseY;
angleY += deltaX;
angleX += deltaY;
lastMouseX = x;
lastMouseY = y;
glutPostRedisplay();
}
if (drag) {
int deltaX = x - lastMouseX;
int deltaY = y - lastMouseY;
objX += deltaX * 0.01f;
objY -= deltaY * 0.01f;
lastMouseX = x;
lastMouseY = y;
glutPostRedisplay();
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1200, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow("城堡");
glEnable(GL_DEPTH_TEST);
//设置正反面都为填充方式
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpec);
//定义材料的光泽度
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, MatShininess);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ModelAmb);
Init();
glutMainLoop();
return 0;
}
最后呈现的效果没有截下来,但是上述代码只要环境配好了,那么就可以直接运行出结果。
共勉