实验十三3DS模型的显示new.docx
《实验十三3DS模型的显示new.docx》由会员分享,可在线阅读,更多相关《实验十三3DS模型的显示new.docx(37页珍藏版)》请在冰点文库上搜索。
实验十三3DS模型的显示new
实验十三3DS模型的显示
一、实验目的
1.实现3DS模型在程序中的显示与漫游
2.实现MDL模型在程序中的显示与漫游
3.了解3DS模型尺寸与OpenGL绘图坐标之间的关系
二、实验环境
硬件要求:
PC机,主流配置,最好为独立显卡,显存512M以上。
软件环境:
操作系统:
WindowsXP。
语言开发工具:
MicrosoftVisualstudio2005/2008,VisualC++。
三、实验内容与要求:
要求:
实验所有步骤所生成的效果截图拷贝到实验报告文档里备查,并附上相应的代码。
WORD文档命名方式:
学号姓名-实验序号-实验名称。
内容:
1.铲车模型显示程序
图1·铲车模型程序效果
仔细研读程序,修改程序,将模型放入上次实验的场景中
在场景中尝试添加其他模型,并查看效果
1.如果屏蔽深度检测代码,模型显示会怎样变化?
2.模型的纹理对场景的效果会有影响吗?
提供的模型(参见实验文件夹3DSModel):
1.汽车(分普通轿车和宝马车)
2.飞机
3.铲车
(如发现贴图有问题,请立即告诉老师,同学们也可自行到网上搜寻模型)
五、设置参考
1)3DS模型导入设置
1.工程文件准备
1)添加头文件
#include"3ds.h"
#include"texture.h"
2)添加源程序
3ds.cpp,
texture.cpp
2.主程序修改步骤
1.变量定义C3DSModeldraw3ds[5];//有多少个模型,数组就定义多大
2.//调入模型文件一般设置init()中,例如
draw3ds[0].Load(“car.3ds”);
draw3ds[1].Load(“house.3ds”);
//模型调入后,位置处在世界坐标系的原点
3.//显示写在显示回调函数Display()中
glEnable(GL_LIGHTING);//启用光源
glEnable(GL_TEXTURE_2D);//启用纹理
//通过图形变换使得模型原来的尺寸和世界坐标系得尺寸保持一致
图形变换glScalef(x,y,z);
draw3ds[0].Render();//显示模型1
draw3ds[1].Render();//显示模型2
glDisable(GL_LIGHTING);//使用后关闭光源
glDisable(GL_TEXTURE_2D);//使用后关闭纹理
4.//释放资源,释放内存
draw3ds[0].Release();
draw3ds[1].Release();
6.注意:
要启用深度检测
六、思考题
哪几个因素影响3DS模型的显示效果?
如果想调用不同大小的模型都能在同一个程序正确地显示,程序应该怎样修改?
七、加分题
在网上查找模型或者自己设计模型,调入自己设计的带光照的3D新场景(须有OpenGL绘制的其他物体)中。
八、演示程序
1)3DSModel_chanche.exe//3DS模型铲车效果演示
九、附属程序
1.铲车模型显示主程序3DSModel(带mp3音乐播放功能)
#include"stdafx.h"
#include
#include
#include"3ds.h"
#include"Texture.h"
#include
#include"fmod.h"////音频库的头文件
#pragmacomment(lib,"fmodvc.lib")//音频库的静态链接库
FSOUND_STREAM*mp3back;
voidinit(void);
voidDisplay(void);
voidKeyboard(intkey,intx,inty);
voiddraw3DSModel();
voidReshape(GLsizeiw,GLsizeih);
voidmyidle();
C3DSModeldraw3ds[5];//有多少个模型,数组就定义多大
floateyex=0,eyey=0,eyez=100,atx=0,aty=0,atz=0;
floatrotatex,rotatey;
intAPIENTRY_tWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPTSTRlpCmdLine,
intnCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
char*argv[]={"hello",""};
intargc=2;//must/shouldmatchthenumberofstringsinargv
glutInit(&argc,argv);//初始化GLUT库;
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);//设置显示模式;(缓冲,颜色类型)
glutInitWindowSize(500,500);
glutInitWindowPosition(1024/2-250,768/2-250);
glutCreateWindow("3D-cubetexture");//创建窗口,标题为“Rotating3DWorld”;
glutReshapeFunc(Reshape);
init();
glutDisplayFunc(Display);//用于绘制当前窗口;
glutIdleFunc(myidle);
glutMainLoop();//表示开始运行程序,用于程序的结尾;
return0;
}
voidinit()
{
//调入模型文件一般设置init()中,例如
draw3ds[0].Load("chanche.3ds");
glClearColor(1,1,1,1);
glEnable(GL_DEPTH_TEST);//启用深度测试
if(FSOUND_Init(44100,32,0))//把声音初始化为khz
{
//载入文件bgmusic.mp3
mp3back=FSOUND_Stream_OpenFile("1.mp3",FSOUND_LOOP_NORMAL,0);
}
FSOUND_Stream_Play(FSOUND_FREE,mp3back);
}
voidDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyex,eyey,eyez,atx,aty,atz,0,1,0);
glRotatef(rotatex,1,0,0);
glRotatef(rotatey,0,1,0);
glScalef(0.5,0.5,0.5);
draw3DSModel();//绘制玩物
glutSwapBuffers();
}
voiddraw3DSModel()
{
glEnable(GL_TEXTURE_2D);
glPushMatrix();
draw3ds[0].Render();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
voidspecialkeyboard(intkey,intx,inty)
{
if(key==GLUT_KEY_UP)
{
eyey+=5;aty+=5;
}
if(key==GLUT_KEY_DOWN)
{
eyey-=5;aty-=5;
}
glutPostRedisplay();
}
voidKeyboard(unsignedcharkey,intx,inty)
{
switch(key)
{
case'w':
eyez-=5;
atz-=5;
break;
case's':
eyez+=5;
atz+=5;
break;
case'a':
//eyex-=5;
eyex-=5;
atx-=5;
break;
case'd':
//eyex+=5;
eyex+=5;
atx+=5;
break;
}
glutPostRedisplay();
}
voidReshape(GLsizeiw,GLsizeih)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90,w/h,2,2500);
glViewport(0,0,w,h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
voidmyidle()
{
Sleep(100);
rotatex+=0.1;
rotatey+=0.1;
glutPostRedisplay();
}
2.读取3DS模型程序3ds.cpp
#include"stdafx.h"
#include"3ds.h"
#include"Texture.h"
#include"glaux.h"
//构造函数
C3DSModel:
:
C3DSModel()
{
//初始化文件指针
m_FilePtr=NULL;
//定义一个默认的材质(灰色)
tMaterialdefaultMat;
defaultMat.isTexMat=false;
strcpy(defaultMat.matName.string,"5DG_Default");
defaultMat.color[0]=192;
defaultMat.color[1]=192;
defaultMat.color[2]=192;
m_3DModel.pMaterials.push_back(defaultMat);
//初始化保存DS模型的结构体
m_3DModel.numOfMaterials=1;
m_3DModel.numOfObjects=0;
}
//析构函数
C3DSModel:
:
~C3DSModel()
{
m_3DModel.pMaterials.clear();
m_3DModel.pObject.clear();
}
//载入ds文件
BOOLC3DSModel:
:
Load(char*strFileName)
{
charstrMessage[128]={0};
tChunkchunk={0};
//打开文件
m_FilePtr=fopen(strFileName,"rb");
//如果文件打开失败
if(!
m_FilePtr)
{
sprintf(strMessage,"3DS文件%s不存在!
",strFileName);
MessageBoxA(NULL,strMessage,"Error",MB_OK);
returnfalse;
}
//读取ds文件的第一个Chunk
ReadChunk(&chunk);
//检查是否是ds文件
if(chunk.ID!
=PRIMARY)
{
sprintf(strMessage,"读取文件%s失败!
",strFileName);
MessageBoxA(NULL,strMessage,"Error",MB_OK);
fclose(m_FilePtr);
returnfalse;
}
//开始读取ds文件
ReadPrimary(chunk.length-6);
//计算每个顶点的法线量
ComputeNormals();
//关闭打开的文件
fclose(m_FilePtr);
m_FilePtr=NULL;
//对有纹理的材质载入该纹理
for(inti=0;i{
if(m_3DModel.pMaterials[i].isTexMat)
{
if(!
BuildTexture(m_3DModel.pMaterials[i].mapName.string,m_3DModel.pMaterials[i].texureId))
{
//纹理载入失败
sprintf(strMessage,"3DS纹理文件载入失败:
%s!
",m_3DModel.pMaterials[i].mapName.string);
MessageBoxA(NULL,strMessage,"Error",MB_OK);
}
}
}
returntrue;
}
//从文件中读取个字节
BYTEC3DSModel:
:
ReadByte(void)
{
BYTEresult=0;
fread(&result,1,1,m_FilePtr);
returnresult;
}
//从文件中读取个字节
WORDC3DSModel:
:
ReadWord(void)
{
returnReadByte()+(ReadByte()<<8);
}
//从文件中读取个字节
UINTC3DSModel:
:
ReadUint(void)
{
returnReadWord()+(ReadWord()<<16);
}
//从文件中读取浮点数
floatC3DSModel:
:
ReadFloat(void)
{
floatresult;
fread(&result,sizeof(float),1,m_FilePtr);
returnresult;
}
//从文件中读取字符串(返回字符串长度)
UINTC3DSModel:
:
ReadString(STRING*pStr)
{
intn=0;
while((pStr->string[n++]=ReadByte())!
=0)
;
returnn;
}
//读取ds的一个Chunk信息
voidC3DSModel:
:
ReadChunk(tChunk*pChunk)
{
fread(&pChunk->ID,1,2,m_FilePtr);
fread(&pChunk->length,1,4,m_FilePtr);
}
//读取ds文件主要Chunk
UINTC3DSModel:
:
ReadPrimary(UINTn)
{
UINTcount=0;//该Chunk内容已读取的字节计数
tChunkchunk={0};//用以保存子Chunk的内容
while(count{
ReadChunk(&chunk);
switch(chunk.ID)
{
casePRIM_EDIT:
ReadEdit(chunk.length-6);
break;
//casePRIM_KEY:
//ReadKeyframe(chunk.length-6);
//break;
default:
fseek(m_FilePtr,chunk.length-6,SEEK_CUR);
break;
}
count+=chunk.length;
}
returncount;
}
//读取ds物体主编辑Chunk
UINTC3DSModel:
:
ReadEdit(UINTn)
{
UINTcount=0;
tChunkchunk={0};
while(count{
ReadChunk(&chunk);
switch(chunk.ID)
{
caseEDIT_MAT:
ReadMaterial(chunk.length-6);
break;
caseEDIT_OBJECT:
ReadObject(chunk.length-6);
break;
default:
fseek(m_FilePtr,chunk.length-6,SEEK_CUR);
break;
}
count+=chunk.length;
}
returncount;
}
//读取ds对象
UINTC3DSModel:
:
ReadObject(UINTn)
{
UINTcount=0;
tChunkchunk={0};
//新的ds对象
t3DObjectnewObject={0};
count+=ReadString(&newObject.objName);
m_3DModel.numOfObjects++;
while(count{
ReadChunk(&chunk);
switch(chunk.ID)
{
caseOBJECT_INFO:
ReadObjectInfo(&newObject,n-count-6);
break;
default:
fseek(m_FilePtr,chunk.length-6,SEEK_CUR);
break;
}
count+=chunk.length;
}
//保存ds对象
m_3DModel.pObject.push_back(newObject);
returncount;
}
//读取ds对象信息
UINTC3DSModel:
:
ReadObjectInfo(t3DObject*pObj,UINTn)
{
UINTcount=0;
tChunkchunk={0};
while(count{
ReadChunk(&chunk);
switch(chunk.ID)
{
caseOBJECT_VERTEX:
{
pObj->numOfVerts=ReadWord();
pObj->pVerts=newVector3[pObj->numOfVerts];
memset(pObj->pVerts,0,sizeof(Vector3)*pObj->numOfVerts);
//按块读取顶点坐标值
fread(pObj->pVerts,1,chunk.length-8,m_FilePtr);
//调换y、z坐标值(由于dMAX坐标系方向与OpenGL不同)
floatfTempY;
for(inti=0;inumOfVerts;i++)
{
fTempY=pObj->pVerts[i].y;
pObj->pVerts[i].y=pObj->pVerts[i].z;
pObj->pVerts[i].z=-fTempY;
}
break;
}
caseOBJECT_FACET:
ReadFacetInfo(pObj,chunk.length-6);
break;
caseOBJECT_UV:
pObj->numTexVertex=ReadWord();
pObj->pTexVerts=newVector2[pObj->numTexVertex];
memset(pObj->pTexVerts,0,sizeof(Vector2)*pObj->numTexVertex);
//按块读取纹理坐标值
fread(pObj->pTexVerts,1,chunk.length-8,m_FilePtr);
break;
default:
fseek(m_FilePtr,chunk.length-6,SEEK_CUR);
break;
}
count+=chunk.length;
}
returncount;
}
//读取面信息
UINTC3DSModel:
:
ReadFacetInfo(t3DObject*pObj,UINTn)
{
UINTcount=0;
tChunkchunk={0};
pObj->numOfFaces=ReadWord();
pObj->pFaces=newtFace[pObj->numOfFaces];
memset(pObj->pFaces,0,sizeof(tFace)*pObj->numOfFaces);
//读取面索引值(第个值为dMAX使用的参数,舍弃)
for(inti=0;inumOfFaces;i++)
{
pObj->pFaces[i].vertIndex[0]=ReadWord();
pObj->pFaces[i].vertIndex[1]=ReadWord();
pObj->pFaces[i].vertIndex[2]=ReadWord();
ReadWord();
}
count+=2+pObj->numOfFaces*8;
STRINGmatName;
intt;
intmatID=0;
while(count{
ReadChunk(&chunk);
switch(chunk.ID)
{
caseFACET_MAT:
{
ReadString(&matName);//材质名称
t=ReadWord();//材质对应的面个数
//查找对应的材质
for(inti=1;i<=m_3DModel.numOfMaterials;i++)
{