OpenGL大作业——可旋转、放大城堡

一、说明

就是老师布置的大作业,要求就是设计上课的一些内容,能够完成一个作业,体现作业量。

二、代码

本人记得是参考网上的一些案例改进的,做的并不算好,就是完成一个任务。

#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;
}

最后呈现的效果没有截下来,但是上述代码只要环境配好了,那么就可以直接运行出结果。

共勉

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值