Axiom3D:數據綁定基本流程


     在前面我們學習OpenGL時,不管繪制如球,立方體,平面,地面,動畫模型中最常用的幾個操作有創建緩沖區,寫入緩沖區.在Axiom中,相關的操作被整合與組織到VertexData,IndexData中,所以在后面,我們會看到Axiom里元素如果要繪畫在屏幕上的元素,幾乎都會包含這二個類的實體.

     在看相關介紹前,我們先看下如下關系圖:

   VertexData主要包含二個類的實體,一個是VertexDeclaration,另一個是VertexBufferBinding.

     VertexDeclaration是用來指定數據的組成結構,比如在前面我們使用OpenGL的混合頂點數組時,會用T2F_N3F_V3F指定對應數組每八個浮點數據一組,前二個指定紋理坐標,中間三個數據指定法線,最后三個數據指定頂點.VertexDeclaration類似這個T2F_N3F_V3F,他包含一系列VertexElement,每個VertexElement指定上面的T2F,N3F,V3F這種類型,請看下面一段代碼:

 1 var decl = mesh.SharedVertexData.vertexDeclaration;
 2 var binding = mesh.SharedVertexData.vertexBufferBinding;
 3 
 4 var offset = 0;
 5 decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position );
 6 offset += VertexElement.GetTypeSize( VertexElementType.Float3 );
 7 decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal );
 8 offset += VertexElement.GetTypeSize( VertexElementType.Float3 );
 9 decl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 );
10 offset += VertexElement.GetTypeSize( VertexElementType.Float2 );
VertexElement
  在中間有AddElement就是增加一個VertexElement,其中Float3,Float2就是指如上的3F,2F.而Position,Normal,TexCoords分別對應上面的P,N,T.說到底,這個decl就是指定了如P3F_N3F_T2F這種結構.
  
  VertexBufferBinding主要成員包含一個 Dictionary  < short ,  HardwareVertexBuffer  >  Bindings的數據結構,其中 HardwareVertexBuffer這個比較重要,可以看下一般如何創建HardwareVertexBuffer,如下:
 
 1 var vertices = new float[32]
 2                {
 3                    -100, -100, 0, // pos
 4                    0, 0, 1, // normal
 5                    0, 1, // texcoord
 6                    100, -100, 0, 0, 0, 1, 1, 1, 100, 100, 0, 0, 0, 1, 1, 0, -100, 100, 0, 0, 0, 1, 0, 0
 7                };
 8 var vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl, 4, BufferUsage.StaticWriteOnly );
 9 binding.SetBinding( 0, vbuf );
10 vbuf.WriteData( 0, vbuf.Size, vertices, true );
VertexBuffer

  看過OpenGL綁定過程的,一定看起來很熟悉是不是,實際差不多,在CreateVertexBuffer里,首先會在HardwareVertexBuffer結合decl與頂點個數4.這里為什么是4,其實大家可以算一下,decl里聲明的是P3F_N3F_T2F,意思是每個頂點有八個數據來指明相關屬性,而vertices的長度是32,就是指明這個數據只包含了4個頂點.然后我們可以計算我們需要申請的顯存長度,sizeInBytes=4*8*sizeof(float)=128.然后如果我們使用OpenGL渲染,就會調用GLHardwareVertexBuffer,這個類的初始化里就使用了glGenBuffers.最后vbuf.WriteData操作就會調用glBufferData把相關數據寫入到顯存里.

     很明顯,對比原來我們常用的OpenGL操作如下:

1         this.vboID = glGenBuffers(1)
2         glBindBuffer(GL_ARRAY_BUFFER,this.vboID)
3         glBufferData (GL_ARRAY_BUFFER, len(vdata)*4, vdata, GL_STATIC_DRAW)
4         this.eboID = glGenBuffers(1)
5         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,this.eboID)
6         glBufferData (GL_ELEMENT_ARRAY_BUFFER, len(vIndex)*4, vIndex,GL_STATIC_DRAW)
glBindBuffer
  可以發現少了點什么,是的,我們只是寫入了頂點數據,對應頂點索引沒有,看看在Axiom里如何使用.
 1 var ibuf = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, 6, BufferUsage.StaticWriteOnly );
 2 
 3 var faces = new short[6]
 4             {
 5                 0, 1, 2, 0, 2, 3
 6             };
 7 sub.IndexData.indexBuffer = ibuf;
 8 sub.IndexData.indexCount = 6;
 9 sub.IndexData.indexStart = 0;
10 ibuf.WriteData( 0, ibuf.Size, faces, true );
IndexBuffer

  會發現不一樣的是,頂點數據用的是HardwareVertexBuffer,而頂點索引用的HardwareIndexBuffer,基本用法一樣,不同的調用的CreateIndexBuffer,結合前面與調試在相關位置,發現還是和前面一樣,一樣會調用glGenBuffers,glBindBuffer,glBufferData.不同前面是GL_ARRAY_BUFFER,這里是GL_ELEMENT_ARRAY_BUFFER.     

     我們知道,在底層不管是OpenGL或是D3D,他們都是C,C++及的語言,針對底層的指針操作,在C#中都由上面的BufferBase的派生類包裝GCHandle提供相關的非托管內存訪問托管對象的方法,能創建防GC回收托管對象.詳細請看GCHandle 結構.在HardwareBuffer里的相關和內存,顯存有關的操作全是用BufferBase來完成.具體請看Axiom3D:Buffer漫談整個代碼是創建一個四個點的面,分別創建頂點與頂點索引緩沖區,相對整個部分代碼如下:

 1         /// <summary>
 2         /// Creates a plane as a submesh of the given mesh
 3         /// </summary>
 4         [OgreVersion( 1, 7, 2 )]
 5         private static void _createPlane( Mesh mesh )
 6         {
 7             var sub = mesh.CreateSubMesh();
 8             var vertices = new float[32]
 9                            {
10                                -100, -100, 0, // pos
11                                0, 0, 1, // normal
12                                0, 1, // texcoord
13                                100, -100, 0, 0, 0, 1, 1, 1, 100, 100, 0, 0, 0, 1, 1, 0, -100, 100, 0, 0, 0, 1, 0, 0
14                            };
15 
16             mesh.SharedVertexData = new VertexData();
17             mesh.SharedVertexData.vertexCount = 4;
18             var decl = mesh.SharedVertexData.vertexDeclaration;
19             var binding = mesh.SharedVertexData.vertexBufferBinding;
20 
21             var offset = 0;
22             decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position );
23             offset += VertexElement.GetTypeSize( VertexElementType.Float3 );
24             decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal );
25             offset += VertexElement.GetTypeSize( VertexElementType.Float3 );
26             decl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 );
27             offset += VertexElement.GetTypeSize( VertexElementType.Float2 );
28 
29             var vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl, 4, BufferUsage.StaticWriteOnly );
30             binding.SetBinding( 0, vbuf );
31 
32             vbuf.WriteData( 0, vbuf.Size, vertices, true );
33 
34             sub.useSharedVertices = true;
35             var ibuf = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, 6, BufferUsage.StaticWriteOnly );
36 
37             var faces = new short[6]
38                         {
39                             0, 1, 2, 0, 2, 3
40                         };
41             sub.IndexData.indexBuffer = ibuf;
42             sub.IndexData.indexCount = 6;
43             sub.IndexData.indexStart = 0;
44             ibuf.WriteData( 0, ibuf.Size, faces, true );
45 
46             mesh.BoundingBox = new AxisAlignedBox( new Vector3( -100, -100, 0 ), new Vector3( 100, 100, 0 ) );
47             mesh.BoundingSphereRadius = Utility.Sqrt( 100*100 + 100*100 );
48         }
createPlane

 


免責聲明!

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



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