JoshWindsor 发表于 2022-11-22 17:20

03 uGUI源码-VertexHelper.cs

VertexHelper Class

定义


[*]A utility class that can aid in the generation of meshes for the UI.
一个工具类,它可以帮助UI生成网格。

This class implements IDisposable to aid with memory management.
这个类实现了IDisposable来帮助内存管理。
字段及属性

private List<Vector3> m_Positions;//顶点位置列表 private List<Color32> m_Colors;//顶点颜色列表 private List<Vector2> m_Uv0S;//网格的第一个纹理坐标集。默认情况下由UI元素使用。 private List<Vector2> m_Uv1S;//网格的第二个纹理坐标集(如果存在)。 private List<Vector2> m_Uv2S;//网格的第三个纹理坐标集(如果存在)。 private List<Vector2> m_Uv3S;//网格的第四个纹理坐标集(如果存在)。 private List<Vector3> m_Normals;//法线列表 private List<Vector4> m_Tangents;//切线列表 private List<int> m_Indices;//定义三角形的索引的列表,决定了MeshRenderer构造三角形的顶点顺序 private static readonly Vector4 s_DefaultTangent = new Vector4(1.0f, 0.0f, 0.0f, -1.0f);//默认切线值 private static readonly Vector3 s_DefaultNormal = Vector3.back;//默认法线值 private bool m_ListsInitalized = false;//以上列表元素是否进行初始化public int currentVertCount{    get {return m_Positions != null? m_Positions.Count : 0;} }//返回当前Buffer中顶点个数 public int currentIndexCount{    get {return m_Indices != null? m_Indices.Count : 0;} }//获取VertexHelper上设置的Indices数。
m_Indices的注意点:
Unity默认是只渲染物体的正面,背面是不渲染的。这里就涉及到构造三角形的顺序。在Unity中以顺时针方向构造三角形,这个三角形就是正面,就被会参与渲染的计算,逆时针就是背面,最终不会显示到屏幕上。
所以必须要注意m_Indices的元素存储顺序。
这也是VertexHelper.cs提供的的Example里vh.AddTriangle(0, 1, 2); vh.AddTriangle(2, 3, 0); 的原因。
UIVertex与以上列表字段的关系

UIVertex类描述


Canvas 用于管理顶点的 Vertex 类。
变量描述color顶点颜色。normal法线。position顶点位置。tangent切线。uv0网格的第一个纹理坐标集。默认情况下由 UI 元素使用。uv1网格的第二个纹理坐标集(如果存在)。uv2网格的第三个纹理坐标集(如果存在)。uv3网格的第四个纹理坐标集(如果存在)。
可见,UIVertex类与VertexHelper类存储的列表字段呈整体与局部的关系,一个UI顶点应当包含以上字段属性。
构造函数

public VertexHelper();//内部实现为空。public VertexHelper(Mesh m)//初始化内部字段,并将Mesh中顶点的值赋给内部成员。成员函数

InitializeListIfRequired


若m_ListsInitalized为false则初始化内部属性,并将m_ListsInitalized标记为true。
private void InitializeListIfRequired();
这里可以注意的是,List的初始化并不是简单的new,而是使用了对象池ListPool<T>,避免了List<T>的重复创建与销毁。
Dispose


确定性清理分配的内存。
//先调用ListPool<T>.Release(T),再将各字段置null,//最后m_ListsInitalized置为falsepublic void Dispose();Clear


清空VertexHelper存储的所有结点。
public void Clear();PopulateUIVertex


用VertexHelper中各顶点属性List的第i个索引值填充一个UIVertex。
public void PopulateUIVertex(ref UIVertex vertex, int i);SetUIVertex


用一个UIVertex设置各顶点属性List的第i个索引值。
public void SetUIVertex(UIVertex vertex, int i);FillMesh


使用VertexHelper中的顶点数据填满一个给定的Mesh。
public void FillMesh(Mesh mesh){      InitializeListIfRequired();          //清空mesh      mesh.Clear();      //这里注意: mesh的顶点不能超过65000,Unity中顶点数量不能超过65000个      if (m_Positions.Count >= 65000)            throw new ArgumentException("Mesh can not have more than 65000 vertices");      mesh.SetVertices(m_Positions);      mesh.SetColors(m_Colors);      mesh.SetUVs(0, m_Uv0S);      mesh.SetUVs(1, m_Uv1S);      mesh.SetUVs(2, m_Uv2S);      mesh.SetUVs(3, m_Uv3S);      mesh.SetNormals(m_Normals);      mesh.SetTangents(m_Tangents);      mesh.SetTriangles(m_Indices, 0);      //从顶点重新计算网格的包围体。      //修改顶点之后,应调用此函数以确保包围体正确。      //分配三角形会自动重新计算包围体。      mesh.RecalculateBounds();}AddVert方法


向VertexHelper存储的数据流中添加一个单独的顶点数据。
public void AddVert(Vector3 position, Color32 color, Vector2 uv0, Vector2 uv1, Vector2 uv2, Vector2 uv3, Vector3 normal, Vector4 tangent);AddTriangle


向VertexHelper存储的数据流中添加一个三角形。
public void AddTriangle(int idx0, int idx1, int idx2){       InitializeListIfRequired();       m_Indices.Add(idx0);       m_Indices.Add(idx1);       m_Indices.Add(idx2);}AddUIVertexQuad


用新添加的Vertex数组前四位元素绘制四边形。
//实际上就是添加前4个顶点进Buffer后调用两次AddTriangle方法。public void AddUIVertexQuad(UIVertex[] verts);AddUIVertexStream


将自定义顶点与指示索引添加进VertexHelper存储的数据流中。
public void AddUIVertexStream(List<UIVertex> verts, List<int> indices);
这里用到了CanvasRenderer.AddUIVertexStream:
接受顶点流并将其拆分为相应的数组(positions、colors、uv0s、uv1s、normals 和 tangents)
public static void AddUIVertexStream (List<UIVertex> verts, List<Vector3> positions, List<Color32> colors, List<Vector2> uv0S, List<Vector2> uv1S, List<Vector3> normals, List<Vector4> tangents);AddUIVertexTriangleStream


基本同AddUIVertexStream,indices由提供的UIVertex列表获取。
public void AddUIVertexTriangleStream(List<UIVertex> verts);
这里用到了CanvasRenderer.SplitUIVertexStreams:
与AddUIVertexStream不同的是,拆分的属性还多了indices。
GetUIVertexStream


通过VertexHelper存储的数据流获取一个UIVertex列表。
(与AddUIVertexTriangleStream相反)
public void GetUIVertexStream(List<UIVertex> stream);
这里用到了CanvasRenderer.CreateUIVertexStream:
将一组顶点分量转换为 UIVertex 流。
public static void CreateUIVertexStream (List<UIVertex> verts, List<Vector3> positions, List<Color32> colors, List<Vector2> uv0S, List<Vector2> uv1S, List<Vector3> normals, List<Vector4> tangents, List<int> indices);<hr>
[*]
*参考:
Unity_UGUI | 通向UGUI源码的入口VertexHelper
页: [1]
查看完整版本: 03 uGUI源码-VertexHelper.cs