以一个博文《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.
运行效果图:
可能有些不如意:
模型大小参次不齐,视角高度不大对,也不能下蹲,跳高,还有一些其它的如光照...等等。