浏览量:1,478

3D场景的漫游,纹理装载

下载内容:

(1)       实现了两种摄像机漫游类和OpenGL纹理装载类

(2)       参考NEHE中提供的教程,实现了个简单的DEMO。

(3)       下载地址:https://github.com/twinklingstar20/download_fly_camera_texture_load

下载说明:

1. 摄像机漫游类的设计

共有两个,SrCameraBase和SrCameraEdit,它们是相互继承的关系,但是它们实现的摄像机漫游的方式不同。这三个类,实现的功能有视口的设置,透视投影的设置和摄像机的设置。

SrCameraBase提供了基本的摄像机漫游的功能,就像CS游戏中人物的漫游方式一样,可以上下左右前后移动,并且旋转。它的定义如下所示,其中涉及到相机坐标的计算,这几个矩阵在《顶点渲染管线》文章中的视点坐标那块有介绍,要注意的就是该小节说的OpenGL矩阵顺序的问题。

/*
\brief Setting some configuration of the tranformations and the camera,including view port transformation,
		projection transformation(only perspective transformation).

This class provides with a simple to fly a camera through a scene, like the person in CS moving in the scene.
*/

class SrCameraBase
{
protected:
	typedef struct
	{
		double	fovy;
		double	zNear;
		double	zFar;
		int		viewX;
		int		viewY;
		int		width;
		int		height;
	}StCameraDesc;

public:
	SrCameraBase(double			doFovy,
			 double			doAspect,
			 double			doZNear,
			 double			doZFar,
			 int			inViewX,
			 int			inViewY,
			 int			unWidth,
			 int			unHeight,
			 const SrPoint3D& origin=SrVector3(0,0,-3));
	~SrCameraBase();
	int viewX();
	int viewY();
	int width();
	int height();
	double fovy();
	double zNear();
	double zFar();

	void setView(int viewX,int viewY);
	void setFovy(double fov);
	void setZNear(double zN);
	void setViewSize(int width,int height);
	void setZFar(double zF);

	/*
	\brief	Set the view port.
	*/
	virtual void setViewPort( );
	/*
	\brief	Set the perspective projection.
	*/
	virtual void setProjection();
	/*
	\brief	Set the configuration of the camera.
	*/
	virtual void setCamera();
	/*
	\brief	In the camera coordination system, there are three axises. The following methods provides
			with interfaces to rotate around an axis or move in the direction of an axis.
	*/

	virtual void rotateAxisX(float theta);
	virtual void rotateAxisY(float theta);
	virtual void rotateAxisZ(float theta);

	virtual void moveAxisX( float theta );
	virtual void moveAxisY( float theta );
	virtual void moveAxisZ( float theta );

	virtual void moveAxis(float nX,float nY,float nZ);

	/*
	\brief	Get the original of the camera.
	*/
	SrPoint3D getEye();
protected:
	void update();
	static float determinant( float* ptrMatrix );

protected:
	float				m_lastMatrix[16];
	SrVector3			m_moveDist;
	SrVector3			m_rotAngle;
	StCameraDesc		m_cameraDesc;
};

SrCameraEdit提供了一个类似于3d max软件编辑模型的摄像机漫游方式。最主要的就是,当你选中一个模型后,摄像机可以绕着模型旋转,而不是摄像机的旋转。也提供了上下左右前后移动摄像机的功能,最后的DEMO演示了这个功能,该类的定义如下所示:

/*
\brief Inherit the class SrCameraBase. We can use it to move camera to edit an object like the software of 3d max.
*/

class SrCameraEdit:public SrCameraBase
{
public:
	SrCameraEdit(double	doFovy,
				double	doZNear,
				double	doZFar,
				int		inViewX,
				int		inViewY,
				int		unWidth,
				int		unHeight,
				const SrPoint3D& origin=SrVector3(0,0,-3),
				const SrVector3& center=SrVector3(0,0,0));

	SrVector3 center();
	void setCenter(SrVector3 center);

	virtual void setCamera();
private:

	SrVector3 m_rotCenter;
};

以SrCameraEdit为例,第一步,定义一个摄像机对象:

SrCameraEdit	g_camera(45.0f,				//透视投影的视场
						0.1f,				//近平面
						10000.0f,			//远平面
						0,0,				//视点位置
						100,100,			//窗口尺寸
						SrVector3(0,2.0f,5.0f));//初始位置

第二步,在消息循环中,窗口发生变化的时候,会改变视口和透视投影的参数,所以在函数ReSizeGLScene中,需要加入下面几行代码:

     g_camera.setViewSize(width,height);

     g_camera.setViewPort();

     g_camera.setProjection();

第三步,在渲染的最前面,加入下面两行代码,摄像机参数就设置完成了。

     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

     g_camera.setCamera();

2. OpenGL纹理装载类

该功能在类SrTextureBase中实现,现在只支持BMP和TGA类型的装载,利用到了以前实现的解析类,关于OpenGL纹理的介绍,包括mipmap概念等,以后会有详细的介绍,这个类的定义如下所示。

 

/*
\brief The information of the texture is stored here.
*/
typedef struct
{ 
	GLuint	id;
	GLint	magFilter;		// Style of texture magnification function	
	GLint	minFilter;		// Style of texture minifying function				
	GLint 	bpp;			// Image Color Depth In Bits Per Pixel.
	GLint 	format;			// Image Type (GL_RGB, GL_RGBA)
	GLint 	width;			// Image Width
	GLint 	height;			// Image Height
}StTextureInfo;

/*
\brief A simple class of loading texture from the images in the application of opengl

*/
class SrTextureBase
{
public:
	SrTextureBase();
	SrTextureBase(	GLuint	uiId,
					GLint	inMagFilter,
					GLint	inMinFilter,
					GLint 	inBpp,
					GLint 	enFormat,
					GLint 	inWidth,
					GLint 	inHeight);
	~SrTextureBase();
	/*
	\brief	Activate this texture.
	*/
	bool	active();
	/*
	\brief	Load texture from the image file.Currently only two image types,'bmp' and 'tga',are supported,
	*/
	bool	loadTexture(char* chPtrFilename);
	/*
	\brief	Build a texture of uniform color
	*/
	void	buildTexture(unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue);	
	/*
	\brief	Change the texture magnification function and then activate this texture.
	*/
	void	changeMagFilter(GLint inMagFilter);
	/*
	\brief	Change the texture minifying function and then activate this texture.
	*/
	void	changeMinFilter(GLint inMinFilter);

private:
	bool		loadBMPTexture(char *chPtrFilename);
	bool		loadTGATexture(char *chPtrFilename);

public:
	StTextureInfo m_textureInfo;
};

 它的使用方法也很简单,只有两步,首先装载图片,当要使用它绘制图形时,激活它。如下所示:

	SrTextureBase	g_boxTexture;
	if (!g_boxTexture.loadTexture("Data/box.bmp"))
	{
		return false;
	}
	g_planeTexture.active();
	drawPlane();

3. Demo介绍

Demo的图片如下所示,地面的纹理采用的是tga文件格式的,而正方体的纹理采用的是bmp文件格式的,在屏幕上左击鼠标并左右移动,场景会绕着白色格子包围的盒子转;当按下键盘上的‘c’,白色格子包围的盒子会改变,这时采用上面相同的操作,场景会绕着新的盒子旋转;滚动鼠标中间的那个圆球,会拉近拉远场景;键盘上的上、下、左、右分别表示场景上移,下移,左移,右移。键盘上的‘L’,提供了场景关照的开关,这是NEHE包含的。

2013-11-23 23-08-50

spacer

Leave a reply