自制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里正常使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM