序
详见官方文档:Unity - Manual: Mesh data (unity3d.com)
Topology:拓扑结构
翻译:
拓扑描述网格具有的面类型。
网格的拓扑定义了索引缓冲区的结构,索引缓冲区又描述了顶点位置如何组合成面。每种类型的拓扑都使用索引数组中不同数量的元素来定义单个面。
Unity支持以下网格拓扑:
三角形
Quad
线
LineStrip
积分
index data:索引数据
翻译:
索引数组包含引用顶点位置数组中元素的整数。这些整数称为索引。
Unity使用索引将顶点位置连接到面中。组成每个面的索引数量取决于网格的拓扑结构。
在Mesh类中,您可以使用Mesh.GetIndices获取此数据,并使用Mesh.SetIndices进行设置。Unity也将此数据存储在Mesh.triangles中,但此旧属性的效率和用户友好性较差。
注意:“点”拓扑不会创建面;相反,Unity在每个位置渲染一个点。所有其他网格拓扑都使用多个索引来创建面或边。
例如,对于具有包含以下值的索引数组的网格:
0,1,2,3,4,5
如果网格具有三角形拓扑,则前三个元素(0,1,2)标识一个三角形,随后的三个单元(3,4,5)标识另一个三角形。顶点可以参与的面数没有限制。这意味着同一个顶点可以多次出现在索引数组中。例如,索引数组可以包含以下值:
0,1,2,1,2,3
如果网格具有三角形拓扑,则前三个元素(0,1,2)标识一个三角形,随后的三个元件(1,2,3)标识与第一个共享顶点的另一个三角形。
winding order:绕序
翻译:
索引数组中每组顶点的顺序称为缠绕顺序。Unity使用缠绕顺序来确定面是面向前还是面向后,进而确定是应该渲染面还是剔除面(将其从渲染中排除)。默认情况下,Unity渲染正面多边形并剔除背面多边形。Unity使用顺时针缠绕顺序,这意味着Unity认为索引沿顺时针方向连接的任何面都是正面的。
上图展示了Unity如何使用缠绕顺序。每个面的顶点顺序决定了该面的法线方向【左手坐标系下,叉乘的方向用左手判断】,Unity将其与当前摄影机透视的正向进行比较。如果法线指向远离当前摄影机的前进方向,则它是向后的。较近的三角形顶点顺序为(1,2,3),从当前的角度来看,这是顺时针方向,因此三角形是面向摄像机的,保留。另一个三角形的顶点顺序是(4,5,6),从当前角度来看,这是逆时针方向,所以这个三角形是背向摄像机的,剔除。
实践
前期准备
添加一个空物体:
给这个空物体添加mesh filter,mesh render组件;mesh render组件的materials项选择default-material。然后新建一个脚本拖给它。
脚本里的代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Draw : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
List<Vector3> verts = new List<Vector3>(); // 顶点坐标
List<int> indices = new List<int>(); // 顶点索引
// 设置绘制一个三角形需要的相关数据
// 从世界坐标系的z轴负无穷处向z轴正无穷处看,这3个顶点是顺时针排列的
// 反过来,从世界坐标系的z轴正无穷处向z轴负无穷处看,这3个顶点是逆时针排列的
verts.Add(new Vector3(0, 0, 0));
verts.Add(new Vector3(0, 1, 0));
verts.Add(new Vector3(1, 0, 0));
indices.Add(0);
indices.Add(1);
indices.Add(2);
// 把数据赋给mesh
Mesh mesh= GetComponent<MeshFilter>().mesh;
mesh.vertices = verts.ToArray();
mesh.triangles = indices.ToArray();
mesh.RecalculateNormals();
}
}
运行
随着视角的变化,顶点的排列顺序也不同。
当顶点顺时针排列时,三角形可见。
当顶点逆时针排列时,三角形不可见,被剔除。