北理工虚拟现实作业-OpenGL下实现3D Max模型的导入

两个礼拜之前,李凤霞老师又布置了一次虚拟现实作业,这次的作业题目是自己从网上找一个汽车的3D模型(一般都是3D Max建的),然后把这个模型导入到OpenGL中,在工程中显示出来,同时能通过鼠标的移动切换视角。由于时间太紧(矩阵分析要考试),这个作业就拜托了宿舍的一个同学,可是没想到最后还是自己做了,就这样也学了点东西(不过不知道有什么用)。

 

先贴下实现效果,车辆是网上找的一个奥迪Q7 3D模型,为了简单不再贴纹理了

 

 

下面说下实现步骤:

1、转换3D Max模型

3D MAX建模后生成的一般都是3ds后缀的文件,直接导入貌似还要在opengl中建立对应的数据结构,上网查了一些资料后,我发现可以用View3D软件把3DS文件转换成.h和.gl两个文件,然后把这两个文件拷贝到工程目录下http://hi.baidu.com/chyrcpxjpxbcege/item/3fe0cd59f170af3e32e0a919 给出了其他的一些导入方法

 

2、添加头文件和初始化

把.h文件添加到工程中去后,在.h文件中加入一个新的类用以导入

class CModernho
{
public:
	CModernho(void);
public:
	~CModernho(void);
public:
	long ScanBytes(int pixWidth, int bitsPixel);
	void MyMaterial(GLenum mode, GLfloat * f, GLfloat alpha);
	void SelectMaterial(int i);
	GLint Gen3DObjectList();
};

CModernho::CModernho(void)
{
}

CModernho::~CModernho(void)
{
}


 

然后在主文件中添加对应的内容

开头定义一个变量,应该对应导入的数目

int listnum;//导入变量


在main函数中初始化时载入该模型

CModernho cmodernho;
listnum = GL3DS_initialize_audi(); //载入audi


最后在渲染函数中调用该模型

glCallList(listnum);// 调用载入函数


这样就得到了以上的效果,工程结构如下:

北理工虚拟现实作业-OpenGL下实现3D Max模型的导入_第1张图片

audi.h就是view3d转换后的文件,很长,其中包含很多点线的信息,显然是把模型的各个点和线都保存下来了

testcar.cpp代码如下:

#include <gl/glaux.h>
#include <gl/glu.h>
#include <GL/glut.h>
#include "math.h"
#include <stdio.h>
#include"audi.h"

int flag=1;
double front_Point_x,front_Point_y,front_Point_z;
double pos_Up[3],pos_Down[3],pos_Motion[3];
double viewmatrix[16],modelviewmatrix[16];
#define GLUT_MIDDLE_UP_BUTTON 0x0003
#define GLUT_MIDDLE_DOWN_BUTTON 0x0004
float PI = 3.141592654;
int listnum;//导入变量
GLfloat xangle = 0.0;
GLfloat yangle = 0.0;
GLfloat oDistance = 5.0;
int cacheX = 0;
int cacheY = 0;
int xSpeed = 1;
int ySpeed = 1;
BOOL light=true; // 光源的开/关
BOOL lp=true; // L键按下了么?
GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; //环境光参数
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; // 漫射光参数
GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f }; // 光源位置
							
void motion(int x, int y) //鼠标响应事件
{
	if (x > cacheX)
	{
		yangle = yangle - xSpeed;
	}
	if (x < cacheX) 
	{
		yangle = yangle + xSpeed;
	}
	if (y > cacheY)
	{
		xangle = xangle + ySpeed;
	}
	if (y < cacheY)
	{
		xangle = xangle - ySpeed;
	}
	glutPostRedisplay();
	cacheX = x;
	cacheY = y;
}

void setView() //设置观察角度
{
	glRotatef(10,1.0,0.0,0.0);
	glRotatef(22,0.0,1.0,0.0);
	glTranslatef(-20.5,-10.0,-55.0);
	glGetDoublev(GL_MODELVIEW_MATRIX,viewmatrix);
}

void SetRC() //设置渲染
{
	glEnable (GL_LINE_SMOOTH);
	glEnable (GL_BLEND);
	glShadeModel(GL_FLAT);
	glFrontFace(GL_CW);
	glEnable (GL_LINE_SMOOTH);
	glEnable (GL_BLEND);
	glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glHint(GL_LINE_SMOOTH,GL_NICEST);
	glEnable(GL_DEPTH_TEST);
	glPolygonMode(GL_BACK,GL_LINE);
	glEnable( GL_COLOR_MATERIAL);
}

void renderWorld() //模拟场景
{
	glFrontFace(GL_CCW);
	glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
	float oXhudu = PI / (180 / xangle); //沿着X轴旋转的角度
	float oYhudu = PI / (180 / yangle); //沿着Y轴旋转的角度
	//设置场景坐标
	GLfloat btm = oDistance * cos(oXhudu);
	GLfloat vpY = oDistance * sin(oXhudu);
	GLfloat vpX = btm * sin(oYhudu);
	GLfloat vpZ = btm * cos(oYhudu);
	if (fabs(xangle) < 90.0) 
	{
		gluLookAt(vpX, vpY, vpZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
	} 
	else 
	{
		if (fabs(xangle) >= 270.0) 
		{
			if (fabs(xangle) >= 360.0) 
			{
				xangle = 0.0;
			}
			gluLookAt(vpX, vpY, vpZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
		} 
		else 
		{
			gluLookAt(vpX, vpY, vpZ, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0);
		}
	}
	if (fabs(yangle) >= 360.0)
	{
		yangle = 0;
	}
	//绘制场景坐标轴
 	glLineWidth(1);
	glBegin(GL_LINES);
	glColor3f(1.0,0.0,0.0);
	glVertex3f(0.0,0.0,0.0);
	glVertex3f(200,0,0);
	glColor3f(0.0,1.0,0.0);
	glVertex3f(0.0,0.0,0.0);
	glVertex3f(0.0,200,0.0);
	glColor3f(0.0,0.0,1.0);
	glVertex3f(0.0,0.0,0.0);
	glVertex3f(0.0,0.0,200.0);
	glEnd();
	glColor3f(0.3,0.5,0.1);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glGetDoublev(GL_MODELVIEW_MATRIX,modelviewmatrix);
	glCallList(listnum);// 调用载入函数
}

void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glClearColor(0.1,0.1,0.1,0.1);
	glPushMatrix();
	setView();
	renderWorld();
	glPopMatrix();
	glutSwapBuffers();
}

void myReshape(int w,int h) //重新绘制场景
{	
	GLfloat nRange = 100.0f;
	glViewport(0,0,w,h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
 	if(w<=h)	//建立裁剪区域(左右下上近远)
	{
		glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,-100,100);
	}
	else
	{
		glOrtho(-nRange*w/h,nRange*w/h,-nRange,nRange,-100,100);
	}
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void mouse(int btn, int state, int x, int y)
{
	if(btn==GLUT_RIGHT_BUTTON ) 
	{
		if(state == GLUT_DOWN)
		{
			if(light)
			{
				glDisable(GL_LIGHT1); // 启用光源
				light=!light;
			}
			else
			{
				glEnable(GL_LIGHT1);
				light=!light;
			}
		}
	}
	glutPostRedisplay();//重新加载

}


int main(int argc, char *argv[]) //主函数
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE|GLUT_DEPTH);
	glutInitWindowPosition(10, 10);
	glutInitWindowSize(800, 800);
	glutCreateWindow("VR-2");
	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // 设置环境光
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // 设置漫射光
	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // 光源位置
	glEnable(GL_LIGHT1); // 启用光源
	CModernho cmodernho;
	listnum = GL3DS_initialize_audi(); //载入audi
	glutDisplayFunc(&myDisplay);
	glutReshapeFunc(&myReshape);
	SetRC();
	glutMouseFunc(mouse);    
	glutMotionFunc(&motion);
	glutMainLoop();
	return 0;
}



至于鼠标控制完全不会,抄了一个同学的代码,不过我知道鼠标响应是在glutMotionFunc(&motion);这个函数中实现的,具体也不深究了,做完这一次后还有最后一次作业,希望不要太难。

你可能感兴趣的:(北理工虚拟现实作业-OpenGL下实现3D Max模型的导入)