进入模型世界--漫游

以一个博文《OpenGL--摄像机漫游》为模板,把我们的3ds模型世界放到这个模板中
把 Vector.h,Vector.cpp,Camera.h,Camera.cpp 和主程序复制过来,CBMPLoader.h,CBMPLoader.cpp 就不用了
主程序加入我们的:

//主程序流程代码:
#include <stdio.h>
#include<gl/glut.h>
#include<gl/glu.h>
#include<gl/gl.h>
//#include <gl\GLAUX.h>

#include "Camera.h"
#include "motionModel.h"//这里只有用到的两个函数声明

/** 定义光源的属性值 */
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };    /**< 环境光参数 */
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };    /**< 漫射光参数 */
GLfloat LightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };   /**< 镜面光参数 */
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };   /**< 光源位置 */

Camera m_Camera;
//CBMPLoader m_Texture;

/** 加载位图纹理(木箱贴图) */
/** 绘制网格地面 */
/** 绘制球体 */
/** 绘制木箱 */

void init(void)
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
    glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    /** 设置光源的属性值 */
    glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);     /**< 设置环境光 */
    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);     /**< 设置漫射光 */
    glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);   /**< 设置漫射光 */

    /** 启用光源和纹理 */
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT1);
    glEnable(GL_TEXTURE_2D);

    /** 载入纹理 */
    //if (!LoadTexture())
    //    MessageBox(NULL, (LPCWSTR)"载入纹理失败!", (LPCWSTR)"错误", MB_OK);

	ModelInit();

    /** 设置摄像机 */
    m_Camera.setCamera(0.0f, 1.5f, 6.0f, 0.0f, 1.5f, 0.0f, 0.0f, 1.0f, 0.0f);
}

void display(void)
{
    /** 用户自定义的绘制过程 */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    /** 放置摄像机 */
    m_Camera.setLook();
    glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);   /**< 设置光源位置 */

    /**< 绘制过程 */
    //DrawGrid();
    //DrawSphere();
    //DrawBox();
	drawAllModel();//绘制所有模型

    glFlush();
}

void ChangeSize(int width, int height)
{
    glViewport(0, 0, width, height);                                    /**< 重新设置视口 */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 1.0f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void motion(int x, int y)
{
    m_Camera.setViewByMouse();

    glutPostRedisplay();
}

void keyboard(unsigned char key, int x, int y)
{
    switch (key) {
        case 27://esc
            exit(0);
            break;
        case 49://1
            m_Camera.setSpeed(0.2f);
            break;
        case 50://2
            m_Camera.setSpeed(0.6f);
            break;
        case 119://w--前进
            m_Camera.moveCamera(m_Camera.getSpeed());
            break;
        case 115://d--左移
            m_Camera.moveCamera(-m_Camera.getSpeed());
            break;
        case 97://a--右移
            m_Camera.yawCamera(-m_Camera.getSpeed());
            break;
        case 100://s--后退
            m_Camera.yawCamera(m_Camera.getSpeed());
            break;
    }

    glutPostRedisplay();
    //printf("========%d\n", key);
}


int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB);
    glutInitWindowSize(800, 600);
    glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) >> 1) - 400, (GetSystemMetrics(SM_CYSCREEN) >> 1) - 300);
    glutCreateWindow("摄像机漫游");
    init();
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(display);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);
    glutMainLoop();
    return 0;
}

把我们的主程序整理成一个motionModel.cpp:

#include <stdio.h>
#include "CLoad3DS.h"



//----------------------------------------

typedef struct _boxbian //外框边界
{
	float xmin,xmax,ymin,ymax,zmin,zmax;
}boxbian;

typedef struct _me3DS
{
    string fileName;//文件名
    t3DModel Model;//模型
	CLoad3DS *gothicLoader;//加载器
	float gothicTrans[10];//模型位置,缩放,旋转
	boxbian bian;
}me3DS;

vector<me3DS> me3ds;      // 所有模型

t3DModel *gothicModel;//这个改为指针

//CLoad3DS *gothicLoader;  

float gothicTrans[10] = {   
    0, 0 , -30 ,     //表示在世界矩阵的位置  
       0 , 0 , 0 ,      //表示xyz放大倍数  
        0 , 0 , 0 , 0  //表示旋转  
};

void LoadAllModel(char* srcDir);//按名称加载模型
void screenshot(char* FileName)  ;//截屏
void setDibiao(GLint w,GLint h,GLint zero); //设置地表长,宽
void loadDibiaoPic(char *szPathName); //载入地表图
void DrawDibiao();

boxbian getbian(t3DModel *Model);//获得模型外框边界

void onFindFilesInDir(char* rootDir, vector<string> &names_3ds)
{
    //srcFiles = (char *)malloc(FILEEMAX * sizeof(char));
    WIN32_FIND_DATA fd;
    ZeroMemory(&fd, sizeof(WIN32_FIND_DATA));

    HANDLE hFile;
    char tmpPath[256];
    char subPath[256];
    ZeroMemory(tmpPath, 256);
    ZeroMemory(subPath, 256);

    BOOL bRet = TRUE;
    static int nFileSize = 0 ;

    //define the format of the basepath
    strcpy(tmpPath, rootDir);
    if(tmpPath[strlen(tmpPath) -1] != '\\')
    {
        strcat(tmpPath, "\\");
    }
    strcat(tmpPath, "*");

		WCHAR wszPath[MAX_PATH+1];                  // 图片的完整路径 ()
		MultiByteToWideChar(CP_ACP, 0, tmpPath, -1, wszPath, MAX_PATH);    // 从ASCII转换为Unicode
    hFile = FindFirstFile(wszPath, &fd);
    while (hFile != INVALID_HANDLE_VALUE && bRet)
    {
        if (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY && 
            wcscmp(fd.cFileName, L".") && wcscmp(fd.cFileName, L".."))
        {
            strcpy(subPath, rootDir);
            if(subPath[strlen(subPath) -1] != '\\')
            {
                strcat(subPath, "\\");
            }
			char tmpchar[MAX_PATH+1];
			int lengthOfMbs = WideCharToMultiByte( CP_ACP, 0, fd.cFileName, -1, NULL, 0, NULL, NULL); 
			WideCharToMultiByte( CP_ACP, 0, fd.cFileName, -1, tmpchar, lengthOfMbs, NULL, NULL); //宽字符转为多字符
            strcat(subPath, tmpchar);
            onFindFilesInDir(subPath, names_3ds);
        }
        else if(!wcscmp(fd.cFileName, L".") || !wcscmp(fd.cFileName, L".."))
        {
            
        }
        else
        {
			char tmpchar[MAX_PATH+1];
			int lengthOfMbs = WideCharToMultiByte( CP_ACP, 0, fd.cFileName, -1, NULL, 0, NULL, NULL); 
			WideCharToMultiByte( CP_ACP, 0, fd.cFileName, -1, tmpchar, lengthOfMbs, NULL, NULL); //宽字符转为多字符
			string str0=string(tmpchar);
			int loc1,loc2;
			loc1=str0.rfind (".3ds");loc2=str0.rfind (".3DS");//去掉其它文件名
			if(loc1==str0.length() -4 || loc2==str0.length() -4)
				names_3ds.push_back(str0);
        }
        bRet = FindNextFile(hFile, &fd);
    }
    FindClose(hFile);
}


//按名称加载模型
void loadNameModel(string filename,vector<me3DS>& me3ds)
{
	me3DS *ds=new(me3DS);

	//初始化
	for(int i=0;i<MAX_TEXTURES;i++)
		ds->Model.texture[i]=0;
	ds->Model.numOfMaterials=0;
	ds->Model.numOfObjects=0;

	ds->fileName=filename;//文件名
	ds->gothicLoader=new(CLoad3DS);
	gothicModel=&ds->Model;//显示指向

	char m0[256];
	//sprintf(m0,"Data/3ds/%s",filename);//加上路径
	string m1="Data/3ds/"+filename;
	strcpy(m0, m1.c_str());
	ds->gothicLoader->Import3DS(gothicModel,m0);//载入
	ds->bian= getbian(gothicModel);//获得外框边界
	
	me3ds.push_back(*ds);//存入
}

//载入模型
void LoadAllModel(char* srcDir,vector<me3DS>& me3ds)
{
	//-------------------------------------
	vector<string> names_3ds;
	//搜索3ds文件(在文件夹中)
	onFindFilesInDir(srcDir, names_3ds);//搜索文件

	  for (unsigned int i = 0; i < names_3ds.size (); i++)
		{
			printf("正在装入 %d 中的第 %d 个模型\n",names_3ds.size (),i+1);
			
			loadNameModel(names_3ds[i], me3ds);
		}	
			printf("装入完成\n");
		
}

//获得模型外框边界
boxbian getbian(t3DModel *Model)
{
	float xmin,xmax,ymin,ymax,zmin,zmax,t;
	xmin=ymin=zmin=9999999.0;//设置一个很大的值
	xmax=ymax=zmax=-9999999.0;//设置一个很小的值

   printf("对象个数:%d\n",gothicModel->numOfObjects);
   //printf("对象vector大小:%d\n",gothicModel->pObject.size());
   //遍历模型中的所有对象
   for(unsigned int i=0;i<gothicModel->pObject.size();i++)
	{
		   //printf("第%d个对象的顶点个数:%d\n",i,gothicModel->pObject[i].numOfVerts);
			NBVector3 *pVerts;      // 对象的顶点
			pVerts=gothicModel->pObject[i].pVerts;
			//遍历对象中的所有顶点
			 for(int j=0;j<gothicModel->pObject[i].numOfVerts;j++)
			 {	
				 //比较大小,留下最小和最大值
				 t=pVerts->x;
				 xmin=(t<xmin)?t:xmin;
				 xmax=(t>xmax)?t:xmax;

				 t=pVerts->y;
				 ymin=(t<ymin)?t:ymin;
				 ymax=(t>ymax)?t:ymax;

				 t=pVerts->z;
				 zmin=(t<zmin)?t:zmin;
				 zmax=(t>zmax)?t:zmax;
				pVerts++;//下一个顶点
			 }
	}
	
	//显示最小最大值
   printf("xmin:%f,xmax:%f\n",xmin,xmax);
   printf("ymin:%f,ymax:%f\n",ymin,ymax);
   printf("zmin:%f,xmax:%f\n",zmin,zmax);
   boxbian bian;
   bian.xmax=xmax;bian.xmin=xmin;bian.ymax=ymax;bian.ymin=ymin;bian.zmax=zmax;bian.zmin=zmin;
   return bian;
}
void dsMatrix()//排列
{
	//分成两排
	unsigned int l=me3ds.size ()/2;
	//按x方向排,计算总长
	float xal=0,//x方向
		t,
	zlmax=0;//z最大
	//第一排
	for (unsigned int i = 0; i < l; i++)
	{
		xal+=me3ds[i].bian.xmax-me3ds[i].bian.xmin;
		t=me3ds[i].bian.zmax-me3ds[i].bian.zmin;
		zlmax=(zlmax>t)?zlmax:t;
	}
	//地表宽(x),长(z)
	int DibiaoChangX=xal;
	int DibiaoKuanZ=zlmax;// 1/2

	//分配模型地址
	xal=-xal/2;//最左点
	zlmax=-zlmax/2;
	t=xal+gothicTrans[0];printf("%f\n",t);
	for (unsigned int i = 0; i < l; i++)
	{
		
		me3ds[i].gothicTrans[0]=t-me3ds[i].bian.xmin+(me3ds[i].bian.xmax-me3ds[i].bian.xmin)/2;//去掉和原来位置相关性
			t+=(me3ds[i].bian.xmax-me3ds[i].bian.xmin);//下一个位置
		me3ds[i].gothicTrans[1]=gothicTrans[1];
		me3ds[i].gothicTrans[2]=zlmax+-me3ds[i].bian.zmin+(gothicTrans[2]-me3ds[i].bian.zmin)/2;//去掉和原来位置相关性

	}	
	//------------------------------------------------
	//第二排
	for (unsigned int i = l; i < me3ds.size (); i++)
	{
		zlmax=(zlmax>t)?zlmax:t;
	}	
		DibiaoKuanZ+=zlmax;//再加 1/2

	//分配模型地址
	zlmax=zlmax/2;
	t=xal+gothicTrans[0];
	for (unsigned int i = l; i < me3ds.size (); i++)
	{
		
		me3ds[i].gothicTrans[0]=t-me3ds[i].bian.xmin+(me3ds[i].bian.xmax-me3ds[i].bian.xmin)/2;//去掉和原来位置相关性
			t+=(me3ds[i].bian.xmax-me3ds[i].bian.xmin);//下一个位置
		me3ds[i].gothicTrans[1]=gothicTrans[1];
		me3ds[i].gothicTrans[2]=zlmax+-me3ds[i].bian.zmin+(gothicTrans[2]-me3ds[i].bian.zmin)/2;//去掉和原来位置相关性

	}	

	//载入地表图
	setDibiao(DibiaoChangX*1.3,DibiaoKuanZ,me3ds[0].bian.ymin);
	//载入地表图
	loadDibiaoPic("Wood-cherry.jpg");

}

//绘制所有模型
void drawAllModel()
{

    /** 绘制过程 */
    glPushMatrix();


		changeObject( gothicTrans );  

		  for (unsigned int i = 0; i < me3ds.size (); i++)
		{
			gothicModel=&me3ds[i].Model;
			//printf("正在绘制 %d 中的第 %d 个模型\n",names_3ds.size (),i+1);
			float xt1,yt1,zt1;
			xt1=	me3ds[i].gothicTrans[0];
			yt1=     me3ds[i].gothicTrans[1];
			zt1=     me3ds[i].gothicTrans[2];

				glTranslatef(xt1,yt1,zt1);// 放到这个位置
			drawModel(*gothicModel, true, false);//绘模型
				glTranslatef(-xt1,-yt1,-zt1);//还原
		}	
			//printf("绘制完成\n");
		  DrawDibiao();
	glPopMatrix();

}

//模型居中显示
void zhong(GLvoid)
{
	//遍历模型的对象,遍历对象顶点,找到x,y,z的最小,最大值,计算模型外框大小,长,宽,高
	//然后计算xyz放大倍数


	float xmin,xmax,ymin,ymax,zmin,zmax,t;
	xmin=ymin=zmin=9999999.0;//设置一个很大的值
	xmax=ymax=zmax=-9999999.0;//设置一个很小的值

   printf("对象个数:%d\n",gothicModel->numOfObjects);
   //printf("对象vector大小:%d\n",gothicModel->pObject.size());
   //遍历模型中的所有对象
   for(unsigned int i=0;i<gothicModel->pObject.size();i++)
	{
		   //printf("第%d个对象的顶点个数:%d\n",i,gothicModel->pObject[i].numOfVerts);
			NBVector3 *pVerts;      // 对象的顶点
			pVerts=gothicModel->pObject[i].pVerts;
			//遍历对象中的所有顶点
			 for(int j=0;j<gothicModel->pObject[i].numOfVerts;j++)
			 {	
				 //比较大小,留下最小和最大值
				 t=pVerts->x;
				 xmin=(t<xmin)?t:xmin;
				 xmax=(t>xmax)?t:xmax;

				 t=pVerts->y;
				 ymin=(t<ymin)?t:ymin;
				 ymax=(t>ymax)?t:ymax;

				 t=pVerts->z;
				 zmin=(t<zmin)?t:zmin;
				 zmax=(t>zmax)?t:zmax;
				pVerts++;//下一个顶点
			 }
	}
	
	//显示最小最大值
   printf("xmin:%f,xmax:%f\n",xmin,xmax);
   printf("ymin:%f,ymax:%f\n",ymin,ymax);
   printf("zmin:%f,xmax:%f\n",zmin,zmax);

      printf("宽度(x差值):%f,\n",xmax-xmin);
      printf("高度(y差值):%f,\n",ymax-ymin);
      printf("深度(z差值):%f,\n",zmax-zmin);
	  float xm,ym,zm,b;
	  xm=xmax-xmin;ym=ymax-ymin;zm=zmax-zmin;
	  b=1.0/max(max(xm,ym),zm)*2;
      printf("放大倍数:%f,\n",b);

	gothicTrans[3]=gothicTrans[4]=gothicTrans[5]=b;//设置放大倍数	
	//移到屏幕中央
	gothicTrans[0]=-(xmin+(xmax-xmin)/2)*b;
	gothicTrans[1]=-(+(ymax-ymin)/2)*b;
	gothicTrans[2]=-(zmin+(zmax-zmin)/2)*b-20;



}


void ModelInit()  
{  
	//搜索文件-----------------------------
	//3ds文件夹
	char* srcDir = "C:\\搜狗高速下载\\Lesson06gj\\Lesson06gj\\Lesson06\\Data\\3DS";//"D:/gong/opengl1/opengl1/Data/3DS";
	//onFindFilesInDir(char* rootDir, vector<string> &names_3ds);
	LoadAllModel(srcDir,me3ds);

	//gothicLoader->Import3DS(&gothicModel, filename3ds);//导入模型,第二个参数是3ds文件的路径,
	zhong();
	dsMatrix();
}
和前面的其它的cpp,应该是这样的,当然象ArcBall.cpp没有用上:

哪个47的就是主cpp.

运行效果图:

可能有些不如意:

模型大小参次不齐,视角高度不大对,也不能下蹲,跳高,还有一些其它的如光照...等等。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值