Unity用Mesh构造Cube和圆

(大部分内容是我自己的理解,如果出现了错误地方望不吝赐教)
我们可以通过控制unity世界中的顶点来生成mesh网格

由于Unity的渲染方式是单向渲染, 我们需要控制每个三角面的法线方向

根据左手定则,我们可以根据法线方向来确定我们顶点的顺序

但是如果只用一个Vector3数组来存储所有三角形的位置信息,会导致大量空间的浪费,所以我们使用类似于OpenGL中的

VAO概念,给所有顶点的逻辑顺序进行编号,然后我们根据对应的index在顶点数组中寻找对应的元素,然后再将这三个点连接成一个三角面

我们根据物体本地坐标系,给cube的六个面,分别标记为front,back,up,down,left,right

以front为例


triangle.jpg

三角面的构造顺序为(0, 3, 2)和(0, 2, 1)

以此类推可以得到以下代码:

void GenerateCube()
    {   
        mesh.vertices = new Vector3[]
        {
            new Vector3(0,0,0),
            new Vector3(1,0,0),
            new Vector3(1,1,0),
            new Vector3(0,1,0),
            new Vector3(0,1,1),
            new Vector3(1,1,1),
            new Vector3(1,0,1),
            new Vector3(0,0,1)
        };
        mesh.triangles = new int[]
        {
            0, 3, 2,//前
            0, 2, 1,
            7, 4, 3,//左
            7, 3, 0,
            6, 5, 4,//后
            6, 4, 7,
            1, 2, 5,//右
            1, 5, 6,
            2, 3, 4,//上
            2, 4, 5,
            1, 7, 0,//下
            1, 6, 7
        };
    }

画完正方体,我们给他手动添加一个shader,这个时候会发现,这个立方体的光照会出现问题,为什么会发生这种问题?


cube

在unity的光照计算中,我们实际上使用顶点法线normal计算光照,但是我们在构成正方体的时候,顶点信息是复用的,由于unity只允许一个顶点对应一个法线,法线会出现覆盖的情况,这样在计算的时候某个点在某个面的法线信息就会丢失,为了正确得到光照,我们需要把所有面分开。

使用Mesh控制生成圆

我们需要使用一个segments变量来控制分割的块数

同时顶点的数目是需要在其基础上加1

//顶点数组大小
int verticesCount = segments + 1;
Vector3[] vertices = new Vector3[verticesCount];
vertices[0] = Vector3.zero;//首元素为圆的中心

为了计算每次分割的步长,我们需要定义一个变量currAngle来记录当前的角度

//计算每个分割的度数(弧度)
float angleDegree = 360.0f;
float angleRad = Mathf.Deg2Rad * angleDegree;
float currAngle = angleRad;//从最大角度开始
float detlaAngle = angleRad / segments;//计算角度变化

在计算的时候,我们需要注意一个问题,我们生成三角顶点顺序的时候是按照顺时针(0,1,2)(0,2,3)(0,3,4)...(0,n-1,n)(0,n,1)最后一个三角形需要拿出单独处理才能把圆形拼接上

for (int i = 1; i < verticesCount; i++)
{
    float cosTheta = Mathf.Cos(currAngle);
    float sinTheta = Mathf.Sin(currAngle);
    vertices[i] = new Vector3(cosTheta * radius,0, sinTheta * radius);
    currAngle -= detlaAngle;
}
//构造三角形
int triangleCount = segments * 3;
int[] triangles = new int[triangleCount];
//这里没有全部处理,
for (int i = 0, vertexIndex = 1; i < triangleCount; i += 3, vertexIndex++)//每次处理三个顶点
{
    triangles[i] = 0;
    triangles[i + 1] = vertexIndex;
    triangles[i + 2] = vertexIndex + 1;
}
//最后一个三角形单独处理
triangles[triangleCount - 3] = 0;
triangles[triangleCount - 2] = verticesCount - 1;
triangles[triangleCount - 1] = 1;

你可能感兴趣的:(Unity用Mesh构造Cube和圆)