• 自制C#版3DS文件的解析器并用SharpGL显示3DS模型


    自制C#版3DS文件的解析器并用SharpGL显示3DS模型

    +BIT祝威+悄悄在此留下版了个权的信息说:

    据说*.3ds格式的3D模型文件是很古老和过时的格式。本文参考了(http://www.spacesimulator.net/wiki/index.php?title=Tutorials:3ds_Loader)和(http://www.cnblogs.com/lookof/archive/2009/03/27/1423695.html),在此表示感谢。本文讲解如何从零开始用C#写一个3ds文件的解析器,然后用SharpGL(C#对opengl的封装)来显示3ds模型。有图有真相。

    http://images.cnblogs.com/cnblogs_com/bitzhuwei/554293/o_3dsViewer1.png

    http://images.cnblogs.com/cnblogs_com/bitzhuwei/554293/o_3dsViewer2.png 

    上图使用的3ds模型文件和贴图文件在此。(spaceship.zip)(spaceshiptexture.bmp

    3DS文件格式

    +BIT祝威+悄悄在此留下版了个权的信息说:

    3ds文件是二进制的。3ds格式的基本单元叫块(chunk)。我们就是读这样一块一块的信息。目录树如下,缩进风格体现了块的父子关系。可见3ds模型文件和XML文件类似,都是只有1个根结点的树状结构

     1 MAIN CHUNK 0x4D4D
     2    3D EDITOR CHUNK 0x3D3D
     3       OBJECT BLOCK 0x4000
     4          TRIANGULAR MESH 0x4100
     5             VERTICES LIST 0x4110
     6             FACES DESCRIPTION 0x4120
     7                FACES MATERIAL 0x4130
     8             MAPPING COORDINATES LIST 0x4140
     9                SMOOTHING GROUP LIST 0x4150
    10             LOCAL COORDINATES SYSTEM 0x4160
    11          LIGHT 0x4600
    12             SPOTLIGHT 0x4610
    13          CAMERA 0x4700
    14       MATERIAL BLOCK 0xAFFF
    15          MATERIAL NAME 0xA000
    16          AMBIENT COLOR 0xA010
    17          DIFFUSE COLOR 0xA020
    18          SPECULAR COLOR 0xA030
    19          TEXTURE MAP 1 0xA200
    20          BUMP MAP 0xA230
    21          REFLECTION MAP 0xA220
    22          [SUB CHUNKS FOR EACH MAP]
    23             MAPPING FILENAME 0xA300
    24             MAPPING PARAMETERS 0xA351
    25       KEYFRAMER CHUNK 0xB000
    26          MESH INFORMATION BLOCK 0xB002
    27          SPOT LIGHT INFORMATION BLOCK 0xB007
    28          FRAMES (START AND END) 0xB008
    29             OBJECT NAME 0xB010
    30             OBJECT PIVOT POINT 0xB013
    31             POSITION TRACK 0xB020
    32             ROTATION TRACK 0xB021
    33             SCALE TRACK 0xB022
    34             HIERARCHY POSITION 0xB030
    3DS块结构
    +BIT祝威+悄悄在此留下版了个权的信息说:

    实际上完整的chunk列表有上千种类型,我们只需解析其中的顶点列表、面列表和纹理UV列表就行了。

    以类型标识为0x4D4D的MAIN CHUNK为例,整个3ds文件的前两个byte必须是0x4D4D,否则就说明这个文件不是3ds模型文件。然后从第3到第6个byte是一个Uint32型的数值,表示整个MAIN CHUNK的长度。由于MAIN CHUNK是整个3ds文件的根结点,它的长度也即整个3ds文件的长度。

    块(Chunk)的结构

    每一个“chunk”的结构如下所示:

    偏移量

    长度

    0

    2

    块标识符

    2

    4

    块长: 块数据 + 子块内容

    6

    n

    块数据

    6+n

    m

    S子块

    +BIT祝威+悄悄在此留下版了个权的信息说:

    读取的思路是:首先根据偏移量和长度找到一个块的标识符,然后据此来判断它是什么块,遇到我们需要的块,就进一步读取,如果不需要,直接跳过这一块,读取下面的块。

    我们的解析器需要顶点、面和贴图UV信息,根据3ds模型文件的树状结构,可以找到需要解析的Chunk如下。

    MAIN CHUNK

    Identifier

    0x4d4d 

    Length

    0 + sub-chunks length

    Chunk father

    None

    Sub chunks

    3D EDITOR CHUNK

    Data

    None

    3D EDITOR CHUNK

    Identifier

    0x3D3D 

    Length

    0 + sub-chunks length

    Chunk father

    MAIN CHUNK

    Sub chunks

    OBJECT BLOCK, MATERIAL BLOCK, KEYFRAMER CHUNK

    Data

    None

    OBJECT BLOCK

    Identifier

    0x4000

    Length

    Object name length + sub-chunks length

    Chunk father

    3D EDITOR CHUNK

    Sub chunks

    TRIANGULAR MESH, LIGHT, CAMERA

    Data

    Object name

    TRIANGULAR MESH

    Identifier

    0x4100

    Length

    0 + sub-chunks length

    Chunk father

    OBJECT BLOCK

    Sub chunks

    VERTICES LIST, FACES DESCRIPTION, MAPPING COORDINATES LIST

    Data

    None

    VERTICES LIST(点数据在这)

    Identifier

    0x4110

    Length

    varying + sub-chunks length

    Chunk father

    TRIANGULAR MESH

    Sub chunks

    None

    Data

    Vertices number (unsigned short)
    Vertices list: x1,y1,z1,x2,y2,z2 etc. (for each vertex: 3*float)

    FACES DESCRIPTION(面数据在这)

    Identifier

    0x4120

    Length

    varying + sub-chunks length

    Chunk father

    TRIANGULAR MESH

    Sub chunks

    FACES MATERIAL

    Data

    Polygons number (unsigned short)
    Polygons list: a1,b1,c1,a2,b2,c2 etc. (for each point: 3*unsigned short)
    Face flag: face options, sides visibility etc. (unsigned short)

    MAPPING COORDINATES LIST(贴图数据在这)

    Identifier

    0x4140

    Length

    varying + sub-chunks length

    Chunk father

    TRIANGULAR MESH

    Sub chunks

    SMOOTHING GROUP LIST

    Data

    Vertices number (unsigned short)
    Mapping coordinates list: u1,v1,u2,v2 etc. (for each vertex: 2*float)

    据此给出Chunk的枚举类型

     1         enum ChunkType
     2         {
     3             MainChunk = 0x4D4D,
     4             _3DEditorChunk = 0x3D3D,
     5             CVersion = 0x0002,
     6             KeyFramerChunk = 0xB000,
     7             MaterialBlock = 0xAFFF,
     8             MaterialName = 0xA000,
     9             AmbientColor = 0xA010,
    10             DiffuseColor = 0xA020,
    11             SpecularColor = 0xA030,
    12             C_MATSHININESS = 0xA040,
    13             TextureMap = 0xA200,
    14             MappingFilename = 0xA300,
    15             ObjectBlock = 0x4000,
    16             TriangularMesh = 0x4100,
    17             VerticesList = 0x4110,
    18             FacesDescription = 0x4120,
    19             FacesMaterial = 0x4130,
    20             MappingCoordinatesList = 0x4140
    21         }
    ChunkType

    解析结果

    +BIT祝威+悄悄在此留下版了个权的信息说:

    解析结果为一个3dsFile类型的实例,它包含若干模型(称为entity)。每个entity都含有描述三维模型的顶点、面和贴图UV信息,据此我们用SharpGL来将其显示出来。

     1          foreach (var entity in _3dsFile.Entities)
     2          {
     3                    gl.Enable(OpenGL.GL_TEXTURE_2D);
     4                    gl.BindTextue(OpenGL.GL_TEXTURE_2D, this.texture.TextureName);
     5                    gl.Begin(SharpGL.Enumerations.BeginMode.Triangles);
     6                    foreach (var triangle in entity.indices)
     7                    {
     8                             var point1 = entity.vertices[triangle.vertex1];
     9                             var uv1 = entity.texcoords[triangle.vertex1];
    10                             gl.TexCoord(uv1.U, uv1.V);
    11                             gl.Vertex(point1.X, point1.Y, point1.Z);
    12                             var point2 = entity.vertices[triangle.vertex2];
    13                             var uv2 = entity.texcoords[triangle.vertex2];
    14                             gl.TexCoord(uv2.U, uv2.V);
    15                             gl.Vertex(point2.X, point2.Y, point2.Z);
    16                             var point3 = entity.vertices[triangle.vertex3];
    17                             var uv3 = entity.texcoords[triangle.vertex3];
    18                             gl.TexCoord(uv3.U, uv3.V);
    19                             gl.Vertex(point3.X, point3.Y, point3.Z);
    20                    }
    21                    gl.End();
    22          }
    23 
    24  
    用SharpGL显示3DS模型

    需要注意的一点是,SharpGL加载的贴图是上下反向的,所以你必须把准备好的贴图上下翻转,才能在SharpGL里正常使用。

  • 相关阅读:
    常用JS判断正则
    Java中final修饰参数的作用
    hibernate实现动态表名
    java urlrewrite
    tomcat下,超链接下载出现乱码页面
    Hibernate 在MyEclipse中配置
    javamail command not implemented
    The Missing Piece
    十六进制颜色码【转载】
    【转载】关于:读写xls文件,提供下载的一个小例子(jxl 的简单运用) 创建文件
  • 原文地址:https://www.cnblogs.com/bitzhuwei/p/write-3ds-parser-and-show-in-sharpgl.html
Copyright © 2020-2023  润新知