现在的位置: 首页 > 综合 > 正文

OpenGL学习笔记(五)—三维地图

2014年01月20日 ⁄ 综合 ⁄ 共 5639字 ⁄ 字号 评论关闭

1.简介        

由于自己对WIN API不熟悉,所以把Nehe例程改成了“纯”C++实现,当然,windows下编程还是用到了<windows.h>里定义的一些宏、结构体.....

        NeHe教程10是用一张.bmp位图实现了一个三维世界,可以键盘控制视角。

(PS.本人用例程里自带的图片会出问题, 于是我把原图片打开用截图工具重新截取就没问题,猜想是原图存储的方式跟读取的方式不一致导致。)

2.效果图



3.实现

Lesson10Main.cpp;

#include <math.h>
#include <stdio.h>
#include <cstdlib>
#include <vector>
#include "../../TE/TEApplication.h"
#include "../../TE/TEGlutWindow.h"
#include "../../TE/TETexture.h";
#include "../../TE/TEFileBitmap.h"
#include "../../TE/TELog.h"
#include "../../TE/TEMacros.h"

using namespace std;

class Lesson10Win : public TEGlutWindow
{
private:
	float m_fHeading, m_fXpos, m_fZpos;

	GLfloat m_fYrot, m_fWalkBias, m_fWalkbiasAngle, m_fLookupDown, m_fZoom;
	GLuint m_uiFilter;

	GLuint  m_vecTexture[3];

	typedef struct tagVERTEX
	{
		float x, y, z;
		float u, v;
	} VERTEX;

	typedef struct tagTRIANGLE
	{
		VERTEX vertex[3];
	} TRIANGLE;

	typedef struct tagSECTOR
	{
		int numtriangles;
		TRIANGLE* triangle;
	} SECTOR;

	SECTOR sector1;
public:
	Lesson10Win();
	~Lesson10Win();

	//! Read the world's coordinate information;
	void readStr(FILE* f, char* string);

	//! Write the coordinate to the array;
	void setUpWorld(void);

	//! Created 3 texutures;
	int loadGLTextures(void);

	//! Window init;
	void onInit();

	//! Render the window;
	void onRender();

	//! Change display when program idle;
	void onIdle();

	//! Deal with key event;
	void onKeyDown(int iKey, char cAscii);
};

Lesson10Win::Lesson10Win()
{

}

Lesson10Win::~Lesson10Win()
{

}

void Lesson10Win::readStr( FILE* f, char* string )
{
	do 
	{
		fgets(string, 255, f);
	} while ((string[0] == '/') || (string[0] == '\n'));
	return;
}

void Lesson10Win::setUpWorld( void )
{
	float x, y, z, u, v;
	int numtriangles;
	FILE* filein;
	char oneline[255];
	filein = fopen("../run/res/World.txt", "rt");
	readStr(filein, oneline);
	sscanf(oneline, "NUMPOLLIES %d\n", &numtriangles);
	sector1.triangle = new TRIANGLE[numtriangles];
	sector1.numtriangles = numtriangles;
	for (int i = 0; i < numtriangles; i++)
	{
		for (int vert = 0; vert < 3; vert++)
		{
			readStr(filein, oneline);
			sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);
			sector1.triangle[i].vertex[vert].x = x;
			sector1.triangle[i].vertex[vert].y = y;
			sector1.triangle[i].vertex[vert].z = z;
			sector1.triangle[i].vertex[vert].u = u;
			sector1.triangle[i].vertex[vert].v = v;
		}
	}

	fclose(filein);
	return;
}

void Lesson10Win::onInit()
{
	m_fHeading = 0, m_fXpos = 0, m_fZpos = 0;
	m_fYrot = 0, m_fWalkBias = 0, m_fWalkbiasAngle = 0, m_fLookupDown = 0 , m_fZoom = 0;
	m_uiFilter = 0;
	if (!loadGLTextures())
	{
		return;
	}
	glEnable(GL_TEXTURE_2D);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glDepthFunc(GL_LESS);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	setUpWorld();
}


void Lesson10Win::onRender()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	GLfloat x_m, y_m, z_m, u_m, v_m;
	GLfloat xtrans = -m_fXpos;
	GLfloat ztrans = -m_fZpos;
	GLfloat ytrans = -m_fWalkBias - 0.25f;
	GLfloat sceneroty = 360.0f - m_fYrot;

	int numtriangles;

	glRotatef(m_fLookupDown, 1.0f, 0.0f, 0.0f);
	glRotatef(sceneroty, 0, 1.0f, 0.0f);

	glTranslatef(xtrans, ytrans, ztrans);
	glBindTexture(GL_TEXTURE_2D, m_vecTexture[m_uiFilter]);

	numtriangles = sector1.numtriangles;

	for (int loop_m = 0; loop_m < numtriangles; loop_m++)
	{
		glBegin(GL_TRIANGLES);
			glNormal3f(0.0f, 0.0f, 1.0f);
			for (int i = 0; i < 3; i++)
			{
				x_m = sector1.triangle[loop_m].vertex[i].x;
				y_m = sector1.triangle[loop_m].vertex[i].y;
				z_m = sector1.triangle[loop_m].vertex[i].z;
				u_m = sector1.triangle[loop_m].vertex[i].u;
				v_m = sector1.triangle[loop_m].vertex[i].v;
				glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
			}
		glEnd();
	}

	glutSwapBuffers();
}

void Lesson10Win::onIdle()
{
	glutPostRedisplay();
}

int Lesson10Win::loadGLTextures( void )
{
	int iStatus = FALSE;
	AUX_RGBImageRec* textureImage[1];
	memset(textureImage, 0, sizeof(void *)*1);
	if ( textureImage[0] = TE::loadAuxBMP("../run/res/Mud.bmp"))
	{
		iStatus = TRUE;
		glGenTextures(3, &m_vecTexture[0]);

		//Nearst Filtered texture;
		glBindTexture(GL_TEXTURE_2D, m_vecTexture[0]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage[0]->sizeX, textureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage[0]->data);

		//Linear filtered texture;
		glBindTexture(GL_TEXTURE_2D, m_vecTexture[1]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage[0]->sizeX, textureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage[0]->data);

		//MipMapped texture;
		glBindTexture(GL_TEXTURE_2D, m_vecTexture[2]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, textureImage[0]->sizeX, textureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, textureImage[0]->data);
	}

	if (textureImage[0])
	{
		if (textureImage[0]->data)
		{
			free(textureImage[0]->data);
		}
		free(textureImage[0]);
	}

	return iStatus;
}

void Lesson10Win::onKeyDown( int iKey, char cAscii )
{
	TE::log(TE::numToString(iKey));

	switch (iKey)
	{
	case 100://left;
		m_fHeading += 1.0f;
		m_fYrot = m_fHeading;
		break;
	case 101://up;
		m_fXpos -= (float)sin(m_fHeading*TE_PI_DIV_180)*0.05f;
		m_fZpos -= (float)cos(m_fHeading*TE_PI_DIV_180)*0.05f;
		if (m_fWalkbiasAngle >= 359.0f)
		{
			m_fWalkbiasAngle = 0.0f;
		}
		else
		{
			m_fWalkbiasAngle += 10.0f;
		}
		m_fWalkBias = (float)sin(m_fWalkbiasAngle*TE_PI_DIV_180)*0.05f;
		break;
	case 102://right;
		m_fHeading -= 1.0f;
		m_fYrot = m_fHeading;
		break;
	case 103://down;
		m_fXpos += (float)sin(m_fHeading*TE_PI_DIV_180)*0.05f;
		m_fZpos += (float)cos(m_fHeading*TE_PI_DIV_180)*0.05f;
		if (m_fWalkbiasAngle <= 1.0f)
		{
			m_fWalkbiasAngle = 359.0f;
		}
		else
		{
			m_fWalkbiasAngle -= 10.0f;
		}
		m_fWalkBias = (float)sin(m_fWalkbiasAngle*TE_PI_DIV_180)*0.05f;
		break;
	default:
		break;
	}

	switch (cAscii)
	{
	case '\r'://enter;
		glutFullScreen();
		break;
	case '\x1b'://esc;
		glutReshapeWindow(640, 480);
		break;
	default:
		break;
	}
}

int main() {
	TEApplication* pApp = new TEApplication();
	Lesson10Win* pWin = new Lesson10Win();
	pApp->run();

	delete pApp;
	delete pWin;
	return 0;
}

抱歉!评论已关闭.