从0开发游戏引擎之使用OpenGL绘制三维球体

        绘制球体的难点主要在于 要在遍历循环中 根据经纬度反复的使用Cos、Sin函数算出球面上的XYZ三个顶点坐标,一直反复计算,最终三角面多的形成了一个球的形状。

        还是老样子,直接贴代码,感兴趣的先自己看看吧。原理后面有空了统一讲!

Ball.h

#pragma once

namespace U3D
{
	class CBall :public CElement
	{
	private:
		GLSphere *sphere=NULL;
		CCTexture *ballTexture;

	public:
		void draw(float deltaTime);
		GLAABB3D getBoundBox() { return GLAABB3D{Vector3D(-9999,-9999,-99999),Vector3D(9999,9999,9999)};}
		GLSphere *getBall();

		void setBall(Vector3D &center, float radius,char*name="res/其他/地球.png");
		CBall(Vector3D &center, float radius,char*name="res/其他/地球.png");
		CBall();
		~CBall();
	};
}

Ball.cpp

#include "Engine.h"


namespace U3D
{

	CBall::CBall()
	{
	}


	CBall::CBall(Vector3D &center,float radius,char *name)
	{
		ballTexture = CTextureManager::getInstance()->addTexture(name);
		setBall(center, radius,name);
	}

	void CBall::setBall(Vector3D &center, float radius,char*name)
	{
		ballTexture = CTextureManager::getInstance()->addTexture(name);
		if (sphere == NULL)
		{
			sphere = new GLSphere;
		}
		sphere->Set(center, radius);
	}


	void CBall::draw(float deltaTime)
	{
		Matrix3D scaleMatrix;
		Matrix3D rotateMatrix;
		Matrix3D transMatrix;

		//放缩图片
		scaleMatrix.Scale(scale.x, scale.y, scale.z);
		//水平翻转
		if (flip == true)
			scaleMatrix._11 *= -1;
		//旋转图片
		Matrix3D tempx, tempy, tempz;
		tempy.YRotate(angle.y);
		tempx.XRotate(angle.x);
		tempz.ZRotate(angle.z);
		rotateMatrix = tempx*tempy*tempz;

		// 平移图片到我们的指定位置
		transMatrix.Translate(pos.x, pos.y, pos.z);
		local_matrix = scaleMatrix*rotateMatrix*transMatrix;

		if (parent == NULL)
		{
			world_color = local_color;
			world_matrix = local_matrix;
		}
		else
		{
			sColor col = parent->getWorldColor();
			world_color.r = local_color.r*col.r;
			world_color.g = local_color.g*col.g;
			world_color.b = local_color.b*col.b;
			world_color.a = local_color.a*col.a;
			world_matrix = local_matrix*parent->getWorldMatrix();//行*列矩阵相乘__计算得到新矩阵
		}

		if (visible == false)
			return;

		Vector3D v;
		float radius = sphere->m_radius;
		Vector3D center = sphere->m_center;

		float dtor = PI / 180.0f;
		int dphi = 10; //纬度
		int dtheta = 10; //经度

		glPushMatrix();
		glColor4fv(world_color.color);
		glMultMatrixf(world_matrix.mat);

		glDisable(GL_CULL_FACE);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, ballTexture->getTextureID());
		glBegin(GL_TRIANGLE_STRIP);
		for (int phi = 0; phi <= 180 - dphi; phi += dphi)
		{
			for (int theta = 0; theta <= 360 - dtheta; theta += dtheta)
			{
				v.x = sinf(phi*dtor)*cosf(theta*dtor);
				v.y = cosf(phi*dtor);
				v.z = sinf(phi*dtor)*sinf(theta*dtor);

				glTexCoord2f(asinf(v.x) / PI + 0.5f, asinf(v.y) / PI + 0.5f);
				glVertex3f(radius*v.x + center.x,
					radius*v.y + center.y,
					radius*v.z + center.z);

				v.x = sinf((phi + dphi)*dtor)*cosf(theta*dtor);
				v.y = cosf((phi + dphi)*dtor);
				v.z = sinf((phi + dphi)*dtor)*sinf(theta*dtor);

				glTexCoord2f(asinf(v.x) / PI + 0.5f, asinf(v.y) / PI + 0.5f);
				glVertex3f(radius*v.x + center.x,
					radius*v.y + center.y,
					radius*v.z + center.z);

				v.x = sinf(phi*dtor)*cosf((theta - dtheta)*dtor);
				v.y = cosf(phi*dtor);
				v.z = sinf(phi*dtor)*sinf((theta - dtheta)*dtor);

				glTexCoord2f(asinf(v.x) / PI + 0.5f, asinf(v.y) / PI + 0.5f);
				glVertex3f(radius*v.x + center.x,
					radius*v.y + center.y,
					radius*v.z + center.z);

				if (phi > -180 && phi < 180)
				{
					v.x = sinf((phi + dphi)*dtor)*cosf((theta - dtheta)*dtor);
					v.y = cosf((phi + dphi)*dtor);
					v.z = sinf((phi + dphi)*dtor)*sinf((theta - dtheta)*dtor);

					glTexCoord2f(asinf(v.x) / PI + 0.5f, asinf(v.y) / PI + 0.5f);
					glVertex3f(radius*v.x + center.x,
						radius*v.y + center.y,
						radius*v.z + center.z);
				}
			}
		}
		glEnd();
		glDisable(GL_TEXTURE_2D);
		glEnable(GL_CULL_FACE);
		glColor4f(1,1,1,1);
		glPopMatrix();
	}




	GLSphere* CBall::getBall()
	{
		return sphere;
	}



	CBall::~CBall()
	{
	}


}

作者对游戏的说明: 首先,您应当以一种批判的眼光来看待本程序。这个游戏是我制作 的第一部RPG游戏,无任何经验可谈,完全按照自己对游戏的理解进 行设计的。当我参照了《圣剑英雄2》的源码之后,才体会到专业游 戏引擎的博大精深。 该程序的内核大约有2000余行,能够处理人物的行走、对话、战斗, 等等。由于该程序的结构并不适于这种规模的程序,故不推荐您详 细研究该程序。所附地图编辑器的源程序我已经添加了详细的注释, 其程序结构也比较合理,可以作为初学VC的例子。 该程序在VC的程序向导所生成的SDI框架的基础上修改而成。它没有 使用任何关于VC底层的东西。程序的绝大部分都是在CgameView类中 制作的,只有修改窗口特征的一段代码在CMainFrm类中。其他的类 统统没有用到。另外添加的一个类是CEnemy类。 整个游戏的故事情节分成8段,分别由Para1.h ~ Para8.h八个文件 实现。由于程序仅仅能够被动的处理各种各样的消息,所以情节的 实现也只能根据系统的一些参数来判断当前应当做什么。在程序使用了冗长的if……else if……结构来实现这种判断。 当然,在我的记录本上,详细的记录了每个事件的判断条件。这种 笨拙的设计当然是不可取的。成都金点所作《圣剑英雄II》采用了 剧本解读的方式,这才是正统的做法。但这也需要更多的编程经验 和熟练的code功夫。 下面列举的是程序编制过程中总结出来的经验和教训。 第一,对话方式应该采用《圣剑英雄II》的剧本方式。 现在的方式把一个段落中所有的对话都混在一个文件中,然后给每 句话一个号码相对应。这样做虽然降低了引擎的难度,却导致剧情的 编写极其繁琐。 第二,运动和显示应当完全分开。 现在的程序中,运动和显示是完全同步的。即:在定时器中调用所有 敌人的运动函数,然后将主角的动画向前推一帧,接着绘制地图,调 用所有敌人的显示函数、重绘主角。这样的好处是不会掉帧,但带来 的问题是,如果要提高敌人的运动速度,那么帧数也跟着上去了。所 以当DEMO版反馈说速度太慢的时候,我修改起来非常困难。而这个问 题到最后也仅仅是将4步一格该成了2步一格。 第三,VC中数组存在上限。如果用“int aaa[1000000000]”定义一个 数组,编译器肯定不会给分配那么大的内存空间。而在这个程序中, 地图矩阵、NPC矩阵都超过了VC中数组的上限。但这一点知道的太晚了。 在1.0版本中已经发现地图最右端缺少了几行,但不知道是什么原因 造成的。(地图编辑器中未出现此问题,因为地图编辑器是用“序列 化”的方式存盘读盘的。)解决这个问题的方法是用“new”来分配 内存空间。 第四,由于不知道应该如何使用“new”和“delete”,几乎所有的DC 都使用了全局变量。这是完全没有必要的。程序运行期大约会耗用20 多M的内存空间,相当于一个大型游戏使用的内存空间了。 另外,在游戏的剧情、美工方面也有许多问题,总之一个词“业余”。 我就不总结了。下一部作品,我将争取在程序上有一个质的飞跃。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值