您的位置:首页 > 其它

纹理贴图

2010-02-08 23:04 260 查看
本文在上一个例子基础上进行修改。去掉圆锥形,并为立方体六边加上纹理贴图,同时增加键盘事件控制旋转角度,Z坐标。实现与Nehe第六、七课一样的效果。(由于本人学习OpenGL为了三维建模,光照方面的代码暂不增加)。
wglwidget.h
#ifndef WGLWIDGET_H
#define WGLWIDGET_H

#include <QtGui/QWidget>
#include <QtOpenGL/QtOpenGL>
#include "ui_wglwidget.h"

class WGLWidget : public QGLWidget , public Ui::WGLWidgetClass
{
	Q_OBJECT

public:
	WGLWidget(QWidget *parent = 0, const QGLWidget* shareEidget = 0,Qt::WFlags flags = 0);
	~WGLWidget();

protected:
	virtual void initializeGL();
	virtual void resizeGL(int w, int h);
	virtual void paintGL();

	virtual void keyPressEvent(QKeyEvent *event);
	virtual void mouseDoubleClickEvent(QMouseEvent *event);
	virtual void closeEvent(QCloseEvent *event);
	virtual void timerEvent(QTimerEvent *event);

private:
	/** @brief	加载纹理*/
	void		loadGLTexture();

private:
	GLfloat		m_fCubeX;		///< 立方体旋转角度
	GLfloat		m_fCubeY;
	GLfloat		m_fCubeZ;

	GLfloat		m_fSpeedX;		///< 旋转速度
	GLfloat		m_fSpeedY;
	GLfloat		m_fSpeedZ;

	enum Texture
	{
		texNull = 0,
		texCube = 2
	};

	GLuint		m_texture[texCube];		///< 纹理贴图

	GLfloat		m_fZ;		///< Z值
};
#endif // WGLWIDGET_H


wglwidget.cpp
#include "wglwidget.h"
#include <math.h>

const GLfloat PI = 3.1415926536f;

WGLWidget::WGLWidget(QWidget *parent /* = 0 */, const QGLWidget* shareEidget /* = 0 */,Qt::WFlags flags /* = 0 */)
	: QGLWidget(parent, shareEidget, flags)
	, m_fCubeX(0.0)
	, m_fCubeY(0.0)
	, m_fCubeZ(0.0)
	, m_fSpeedX(0.5)
	, m_fSpeedY(1)
	, m_fSpeedZ(0.2)
	, m_fZ(-6.0)
{
	setupUi(this);

	setMinimumSize(320,240);

	resize(640,480);
	setWindowTitle(tr("3D空间"));

	// 启用定时器
	startTimer(10);
}

WGLWidget::~WGLWidget()
{

}

void WGLWidget::initializeGL()
{
	glShadeModel(GL_SMOOTH);

	glClearColor(0.0,0.0,0.0,0.0);
	glClearDepth(1.0);

	glEnable(GL_DEPTH_TEST);

	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);

	// 开启纹理
	glEnable(GL_TEXTURE_2D);

	loadGLTexture();
}
void WGLWidget::resizeGL(int w, int h)
{
	// 视口
	glViewport(0,0,(GLint)width(),(GLint)height());

	// 投影变换
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(45.0,(GLfloat)width() / (GLfloat)height(),0.1,100.0);

	// 视图模型变换
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
void WGLWidget::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glPushMatrix();

	// 所有面都按照逆时针方向绘制

	// 绘制立方体
	// 右移.5个单位
	glTranslatef(0.0,0.0,m_fZ);
	// 饶XYZ族旋转立方体
	glRotatef(m_fCubeX,1.0,0.0,0.0);
	glRotatef(m_fCubeY,0.0,1.0,0.0);
	glRotatef(m_fCubeZ,0.0,0.0,1.0);
	// 开始绘制
	glBindTexture(GL_TEXTURE_2D,m_texture[0]);
	glBegin(GL_QUADS);
		//顶面
		glColor3f(0.0,1.0,0.0);		// 颜色改为蓝色
		glTexCoord2f(1.0,0.0);glVertex3f(1.0,1.0,1.0);
		glTexCoord2f(1.0,1.0);glVertex3f(1.0,1.0,-1.0);
		glTexCoord2f(0.0,1.0);glVertex3f(-1.0,1.0,-1.0);
		glTexCoord2f(0.0,0.0);glVertex3f(-1.0,1.0,1.0);
		// 底面
		glColor3f(1.0f,0.5f,0.0f);	// 颜色改成橙色
		glTexCoord2f(1.0,0.0);glVertex3f(1.0,-1.0,1.0);
		glTexCoord2f(1.0,1.0);glVertex3f(-1.0,-1.0,1.0);
		glTexCoord2f(0.0,1.0);glVertex3f(-1.0,-1.0,-1.0);
		glTexCoord2f(0.0,0.0);glVertex3f(1.0,-1.0,-1.0);
	glEnd();

	glBindTexture(GL_TEXTURE_2D,m_texture[1]);
	glColor3f(1.0,1.0,1.0);
	glBegin(GL_QUADS);
		// 左面
		glTexCoord2f(1.0,0.0);glVertex3f(-1.0,-1.0,1.0);
		glTexCoord2f(1.0,1.0);glVertex3f(-1.0,1.0,1.0);
		glTexCoord2f(0.0,1.0);glVertex3f(-1.0,1.0,-1.0);
		glTexCoord2f(0.0,0.0);glVertex3f(-1.0,-1.0,-1.0);
		// 前面
		glTexCoord2f(1.0,0.0);glVertex3f(1.0,-1.0,1.0);
		glTexCoord2f(1.0,1.0);glVertex3f(1.0,1.0,1.0);
		glTexCoord2f(0.0,1.0);glVertex3f(-1.0,1.0,1.0);
		glTexCoord2f(0.0,0.0);glVertex3f(-1.0,-1.0,1.0);
		// 右面
		glTexCoord2f(1.0,0.0);glVertex3f(1.0,-1.0,-1.0);
		glTexCoord2f(1.0,1.0);glVertex3f(1.0,1.0,-1.0);
		glTexCoord2f(0.0,1.0);glVertex3f(1.0,1.0,1.0);
		glTexCoord2f(0.0,0.0);glVertex3f(1.0,-1.0,1.0);
		// 里面
		glTexCoord2f(1.0,0.0);glVertex3f(-1.0,-1.0,-1.0);
		glTexCoord2f(1.0,1.0);glVertex3f(-1.0,1.0,-1.0);
		glTexCoord2f(0.0,1.0);glVertex3f(1.0,1.0,-1.0);
		glTexCoord2f(0.0,0.0);glVertex3f(1.0,-1.0,-1.0);
	glEnd();

	glPopMatrix();
}

void WGLWidget::keyPressEvent(QKeyEvent *event)
{
	switch(event->key())
	{
	case Qt::Key_Home:
		m_fZ += 0.2;
		break;
	case Qt::Key_End:
		m_fZ -= 0.2;
		break;
	case Qt::Key_Left:
		m_fSpeedX -= 0.01;
		break;
	case Qt::Key_Right:
		m_fSpeedX += 0.01;
		break;
	case Qt::Key_Up:
		m_fSpeedY -= 0.01;
		break;
	case Qt::Key_Down:
		m_fSpeedY += 0.01;
		break;
	default:
		break;
	}
}

void WGLWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
	if(windowState() & Qt::WindowFullScreen)
		showNormal();
	else
		showFullScreen();
}

void WGLWidget::timerEvent(QTimerEvent *event)
{
	m_fCubeX -= m_fSpeedX;
	m_fCubeY -= m_fSpeedY;
	m_fCubeZ += m_fSpeedZ;

	update();
}

void WGLWidget::closeEvent(QCloseEvent *event)
{
	QMessageBox box;
	box.setWindowTitle(tr("退出"));
	box.setIcon(QMessageBox::Warning);
	box.setText(tr("确定要关闭OpenGL窗口吗?"));
	box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
	if(QMessageBox::No == box.exec())
	{
		event->ignore();
		return;
	}

	QWidget::closeEvent(event);
}

void WGLWidget::loadGLTexture()
{
	QImage tex,buffer;
	QString str("image/cube%1.bmp");

	// 申请两个纹理空间
	glGenTextures(texCube,&m_texture[0]);

	// 加载图片被生成纹理
	for(short i=0;i<texCube;++i)
	{
		buffer.load(str.arg(i+1));
		tex = QGLWidget::convertToGLFormat(buffer);

		// 绑定纹理、若需要取消纹理,第二个参数可以传入
		// 该函数放入glBegin()与glEnd()之间没有绑定作用
		glBindTexture(GL_TEXTURE_2D,m_texture[i]);

		// 生成纹理
		// glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,tex.width(),tex.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,tex.bits());
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3,tex.width(),tex.height(),GL_RGBA,GL_UNSIGNED_BYTE,tex.bits()); 

		// 设置纹理精度
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	}
}



代码效果如图:



图1.1 程序运行效果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: