关于3ds_3dsmax特效
关于3ds由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“3dsmax特效”。
3ds模型文件有许多块组成,每个块首先描述气候的信息类别,即该块是如何组成的,块的信息类别是用ID来标识的,块还包含了下一个块的相对位置信息。因此即使你不了解一个块的含义,你也可以很容易的跳过它,因为其中指出了下一个块相对该块的起始位置的偏移字节数。与许多文件格式一样,3ds模型二进制文件中的数据也是按低位在前高位在后的方式组织的,例如,两个十六进制字节:4A5C组成的整数型,表明5C高字节位,4A是低字节位。对于长整型如4A5C3B8F,表明5C4A是低字节,而8F3B是高字节。
关于块的定义:块的前两项信息分别为:块的ID和块的长度(也即下一个块相对与该块的字节偏移量),块的ID是一个整数型,而块的长度是一个长整数型。每个块实际上是一个层次结构,不同类型(ID)的块,其层次结构也不相同。3DS模型文件中有一个基本块,其ID是4D4D,每一个3DS模型文件的开头都是由这样的块构成。基本块内的块称为主块,它包含3D编辑器块和关键帧块,其中3D编辑器块包含材质列表块、两配置块、视口定义块、物体定义块等,这其中的块又可以逐渐包含一些块,总之3DS模型文件是有块组成的一种层次结构。
读取3ds文件到自定义的图形数据结构中。
我们需要定义9个全局结构,分别用来定义模型的面、顶点、纹理映射、面材质列表、颜色块、纹理、面材质、形体对象和场景对象的结构。
面结构包含顶点序号p0,p1,p2以及有关顶点顺序的面信息flags,其代码如下:typedef struct {
unsigned short p0,p1,p2;
short flas;
}H3dsFace;
顶点结构包含该顶点的3维坐标信息x、y、z,其代码如下:
typedef struct{
float x,y,z;
}H3dVert;
纹理映射结构包含为顶点定义的两个浮点型纹理映射坐标u、v,其代码如下:
typedef struct{
float u,v;
}H3dsMap;
材质列表结构包含为材质的名称、与该材质相关的面的数目、相关的面列表的序号,其代码如下:
typedef struct{
char name[MAXNAMESIZE];
unsigned short NumFaces;
short *faces;
}H3dMatList;
颜色结构包含为3个浮点数,分别为颜色的红、绿、蓝分量,其代码如下:
typedef struct{
floatred,green,blue;
}H3dsRGBColor;
纹理结构包含纹理名称以及一个相关的选项,其代码如下:
typedef struct{
char texturename[MAXNAMESIZE];
short option;
}H3dsTexture;
材质对象结构包含材质名称、环境光、漫反射光、镜面光、材质、透明度等,其代码如下: typedef struct{
char name[MAXNAMESIZE];
H3dsRGBColor ambient;
H3dsRGBColor diffuse;
H3dsRGBColor specular;
short mat_type;
int doublesided;
int offset;
float alpha;
}H3dsMat;
形体对象是整个3DS模型的核心部分,包含形体名称、形体中顶点个数、面个数、顶点列表、面列表、平移矩阵等一些信息,其代码如下:
typedef struct{
char name[MAXNAMESIZE];//形体名称
unsigned short NumFaces;//面个数
unsigned short NumVerts;//定点个数
unsigned short NumMaps;//纹理个数
int matrix;//1 if transformation matrix is loader;
unsigned short NumBindings;//材质种类
H3dsFace *facelist;//面列表
H3dsVert *vertlist;//顶点列表
H3dsMap *maplist;//纹理列表
Float TraMatrix[3*4];//转换矩阵
H3dsMatList *bindings;//binds faces to materials
int offset;//our starting index into outgl’s vertex list
}H3dsMeshObj;
场景对象是我们需要获取3DS模型数据的最终进入的结构,其中包含3DS模型数据所有形体对象的个数,形体对象列表、材质数目、才知列表,其代码如下:
typedef struct{
unsigned short meshobjs;
H3dsMeshObj *meshobjlist;
unsigned short NumMaterials;
H3dsMat * material;
}H3dsScence;
具体操作时,我们定义了读入当前形体对象的顶点列表函数ReadVertList(H3dsMeshObj *meshobj),读入当前形体对象的面列表函数ReadFaceList(H3dsMeshObj *meshobj),读入纹理映射坐标函数ReadmapList(H3dsMeshObj *meshobj),读入形体数据结构函数ReadTriMeshBlocks(int position ,char *name),读入物体函数块函数ReadObjecBlocks(int postion)等。根据3DS模型文件有块组成,每个块有ID标识,且块还包含下一块的相对信息的特点,定义好获取模型的数据结构和操作函数以后,我们可以很方便地实现模型的读取。
在vc++6.0中要利用Opengl将以上的模型数据绘出来还是一件难事,因此我们获得模型数据后,并不急于将他们绘出来,而是将他转换到另外一个易于读取的数据结构中。
我们定义易于OpenGl绘制的数据结构如下:
//颜色结构
typedef struct{
GLfloat red,green,blue,aopha;
}OUTGL_RGB;
//顶点结构(顶点纹理,法向量,顶点坐标)
typedef struct{
GLfloat u,v;
GLfloat nx,ny,nz;
GLfloat x,y,z;
}OUTGL_VERTEX;
//三角形法向量结构
typedef struct{
GLfloatn0,n1,n2;
}OUTGL_NORMAL;
//三角形结构
typedef struct{
GLuint p0,p1,p2;
}OUTGL_TRIANGLE;
//三角形面结构
typedef struct{
GLuint p0,p1,p2;
GLfloat n0,n1,n2;
}OUTGL_SURFACE;
//三角形列表节点 struct OUTGL_TRIANGLENODE{OUTGL_SURFACE *triangle;struct OUTGL_TRIANGLENODE *next;};typedef struct OUTGL_TRIANGLENODE TRIANGLENODE;//多边形结构 typedef struct{char name[50];OUTGL_RGB anbient;OUTGL_RGB diffuse;OUTGL_RGB specular;int doublesided;GLuint NumTriangles;OUTGL_FACE *TriangleIndexList;OUTGL_TRIANGLE *CrunchedTiangleIndexList;Char texturename[50];GLuint textureID;GLuint NumStripts;GLuint *StripStart;GLuint *StripLength;GLuint NumStripPoints;GLuint *StripPoint;}POLYGONLIST;//模型对象 typedef struct{GLuint NumVertex;
OUTGL_VERTEX *VertexLists;
GLuint NumPolygon;
GLuint stript;
POLYGONLIST * PolygonLists;
}M3DSObject;
重点是:模型的最终绘制
void Draw3DSObject(M3DSObject *object)
{
unsigned int i ,j;
int current;
if(!object->strip)
{
glInterleavedArrays(GL_T2F_N3F_V3F,0,object->VertexLists);
for(unsigned int m=0;mNumPolygon;m++)
{
glMaterialfv(GL_FRONT,GL_AMBIENT,(GLfloat*)&object->PolygonLists[m].ambient);glMaterialfv(GL_FRONT,GL_DIFFUSE,(GLfloat*)&object->PolygonLists[m].diffuse);glMaterialfv(GL_FRONT,GL_SPECULAR,(GLfloat*)&object->PolygonLists[m].specular);glDrawElements(GL_TRIANGLES,object->PolygonLists[m].NumTriangles*3,GL_UNSIGNED_INT,object->PolygonLists[m].CrunchedTriangleIndexList);
}
}
else{
glInterleavedArrays(GL_T2F_N3F_V3F,0,object->VertexLists);
for(i=0;iNumPolygon;i++)
{
glMaterialfv(GL_FRONT,GL_AMBIENT,(GLfloat*)&object->PolygonLists[m].ambient);
glMaterialfv(GL_FRONT,GL_DIFFUSE,(GLfloat*)&object->PolygonLists[m].diffuse);glMaterialfv(GL_FRONT,GL_SPECULAR,(GLfloat*)&object->PolygonLists[m].specular);current=0;
for(f=0;iPolygonLists[i],;f++)
{
glDrawElements(GL_TRIANGLES_STRIP,object->PolygonLists[i].StripLength[j],GL_UNSIGNED_INT,object->PolygonLists[i].StripPoint[current]);
current+=object->PolygonLists[i].StripLength[j];
}
}
}
}
笔记摘自《Visual c++ 编程技巧典型案例解析(图形图像处理与数据库编程)》的第1章(图形图像处理编程)事例30(在Visual C++6.0中利用OpenGL实现3DS模型的交互控制)。(P148页)