(五)Cube

1.概述

Unity自带cube模型,但是此文实现,分基础版和完善版。基础版不进行顶点法线计算,完善版会进行法线计算,结果会跟自带cube比较接近。

2.基础版Cube

2.1 基类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]
public class CreateMeshBase : MonoBehaviour
{
    MeshFilter meshFilter;

    protected Mesh mesh;

    protected virtual Vector3[] Vertices { get; }
    protected virtual int[] Triangles { get; }
    protected virtual Vector3[] Normals { get; }
    protected virtual Vector2[] Uvs { get; }
    protected virtual string MeshName { get; }

    protected virtual void Start()
    {
        GetMeshFilter();
    }

    protected virtual void Reset()
    {
        GetMeshFilter();
    }

    protected virtual void OnValidate()
    {
        GetMeshFilter();
    }

    void GetMeshFilter()
    {
        if (meshFilter == null)
        {
            meshFilter = GetComponent<MeshFilter>();
            mesh = new Mesh();            
        }

        mesh.triangles = null;
        mesh.uv = null;
        mesh.vertices = null;

        mesh.name = MeshName;
        mesh.vertices = Vertices;
        mesh.triangles = Triangles;
        mesh.uv = Uvs;

        meshFilter.mesh = mesh;
    }

    private void OnDrawGizmos()
    {
        if (Vertices == null) return;

        Gizmos.color = Color.red;
        Gizmos.DrawSphere(Vector3.zero, 0.5f);

        Gizmos.color = Color.blue;

        for (int i = 0; i < Vertices.Length; i++)
        {
            Gizmos.DrawSphere(Vertices[i], 0.3f);
        }
    }
}

2.2 Cube代码

代码即为定义八个顶点,然后依次设置三角形即可。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateCube : CreateMeshBase
{
    public float halfLength = 5;

    protected override string MeshName
    {
        get
        {
            return "Cube Mesh";
        }
    }

    protected override Vector3[] Vertices
    {
        get
        {
            Vector3[] vertices = new Vector3[8];
            vertices[0] = new Vector3(-halfLength, -halfLength, -halfLength);
            vertices[1] = new Vector3(halfLength, -halfLength, -halfLength);
            vertices[2] = new Vector3(halfLength, -halfLength, halfLength);
            vertices[3] = new Vector3(-halfLength, -halfLength, halfLength);

            vertices[4] = new Vector3(-halfLength, halfLength, -halfLength);
            vertices[5] = new Vector3(halfLength, halfLength, -halfLength);
            vertices[6] = new Vector3(halfLength, halfLength, halfLength);
            vertices[7] = new Vector3(-halfLength, halfLength, halfLength);

            return vertices;
        }
    }

    protected override int[] Triangles
    {
        get
        {
            int[] triangles = new int[36]
            {
                0,1,3,
                3,1,2,
                4,6,5,
                4,7,6,
                1,6,2,
                1,5,6,
                0,3,4,
                4,3,7,
                0,4,1,
                1,4,5,
                3,2,6,
                3,6,7
            };

            return triangles;
        }
    }
}

3.完善版Cube

3.1 基础版Cube的问题

基础版Cube由于三个面公用一个顶点,导致此顶点处的法线和切线无法定义,所以需要分离顶点。这样顶点位置存在三个相互重合的点,每个点只跟自己对应的平面产生关系。

3.2 完善版Cube顶点

新Cube生成方法实在基础版基础上生成的,但是定点数由8个变成36个,即根据基础版的三角形数组生成。如下所示

    protected override Vector3[] Vertices
    {
        get
        {
            Vector3[] vertices = new Vector3[8];
            vertices[0] = new Vector3(-halfLength, -halfLength, -halfLength);
            vertices[1] = new Vector3(halfLength, -halfLength, -halfLength);
            vertices[2] = new Vector3(halfLength, -halfLength, halfLength);
            vertices[3] = new Vector3(-halfLength, -halfLength, halfLength);

            vertices[4] = new Vector3(-halfLength, halfLength, -halfLength);
            vertices[5] = new Vector3(halfLength, halfLength, -halfLength);
            vertices[6] = new Vector3(halfLength, halfLength, halfLength);
            vertices[7] = new Vector3(-halfLength, halfLength, halfLength);

            int[] triangles = new int[36]
            {
                0,3,1,
                3,2,1,
                4,5,6,
                4,6,7,
                1,2,6,
                1,6,5,
                0,4,3,
                4,7,3,
                0,1,4,
                1,5,4,
                3,6,2,
                3,7,6
            };

            cubeVertices = new Vector3[36];

            for (int i = 0; i < cubeVertices.Length; i++)
            {
                cubeVertices[i] = vertices[triangles[i]];
            }

            return cubeVertices;
        }
    }

3.3 三角形数组

根据3.2生成的新的顶点数组,此时三角形数组值即为其索引,如下所示:

   protected override int[] Triangles
    {
        get
        {
            /*int[] triangles = new int[36]
            {
                0,1,3,
                3,1,2,
                4,6,5,
                4,7,6,
                1,6,2,
                1,5,6,
                0,3,4,
                4,3,7,
                0,4,1,
                1,4,5,
                3,2,6,
                3,6,7
            };*/

            int[] triangles = new int[36];

            for (int i = 0; i < triangles.Length; i++)
            {
                triangles[i] = i;
            }

            return triangles;
        }
    }

3.4 法线数组

基础版cube看起来与unity自带的相比比较奇怪,这是因为没有设置顶点的法向。由于基础版公用顶点,所以法线无法定义,所以新版本法线则比较容易。如下所示:

    protected override Vector3[] Normals
    {
        get
        {
            Vector3[] normals = new Vector3[36];

            for (int i = 0; i < normals.Length - 2; i+=3)
            {
                Vector3 normal = Vector3.Cross(cubeVertices[i + 1] - cubeVertices[i], cubeVertices[i + 2] - cubeVertices[i]);

                for (int j = 0; j < 3; j++)
                {
                    normals[i + j] = normal;
                }
            }

            return normals;
        }
    }

3.5 完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateNewCube : CreateMeshBase
{
    public float halfLength = 5;

    private Vector3[] cubeVertices = new Vector3[36];

    protected override string MeshName
    {
        get
        {
            return "Cube Mesh";
        }
    }

    protected override Vector3[] Vertices
    {
        get
        {
            Vector3[] vertices = new Vector3[8];
            vertices[0] = new Vector3(-halfLength, -halfLength, -halfLength);
            vertices[1] = new Vector3(halfLength, -halfLength, -halfLength);
            vertices[2] = new Vector3(halfLength, -halfLength, halfLength);
            vertices[3] = new Vector3(-halfLength, -halfLength, halfLength);

            vertices[4] = new Vector3(-halfLength, halfLength, -halfLength);
            vertices[5] = new Vector3(halfLength, halfLength, -halfLength);
            vertices[6] = new Vector3(halfLength, halfLength, halfLength);
            vertices[7] = new Vector3(-halfLength, halfLength, halfLength);

            int[] triangles = new int[36]
            {
                0,3,1,
                3,2,1,
                4,5,6,
                4,6,7,
                1,2,6,
                1,6,5,
                0,4,3,
                4,7,3,
                0,1,4,
                1,5,4,
                3,6,2,
                3,7,6
            };

            cubeVertices = new Vector3[36];

            for (int i = 0; i < cubeVertices.Length; i++)
            {
                cubeVertices[i] = vertices[triangles[i]];
            }

            return cubeVertices;
        }
    }

    protected override int[] Triangles
    {
        get
        {
            /*int[] triangles = new int[36]
            {
                0,1,3,
                3,1,2,
                4,6,5,
                4,7,6,
                1,6,2,
                1,5,6,
                0,3,4,
                4,3,7,
                0,4,1,
                1,4,5,
                3,2,6,
                3,6,7
            };*/

            int[] triangles = new int[36];

            for (int i = 0; i < triangles.Length; i++)
            {
                triangles[i] = i;
            }

            return triangles;
        }
    }

    protected override Vector3[] Normals
    {
        get
        {
            Vector3[] normals = new Vector3[36];

            for (int i = 0; i < normals.Length - 2; i+=3)
            {
                Vector3 normal = Vector3.Cross(cubeVertices[i + 1] - cubeVertices[i], cubeVertices[i + 2] - cubeVertices[i]);

                for (int j = 0; j < 3; j++)
                {
                    normals[i + j] = normal;
                }
            }

            return normals;
        }
    }

    //override 
}

4.结语

即使完善版cube也未进行uv定义以及切线定义。切线一般均为Vector4类型,值为相应切向或者(-1,0,0,-1)。至于uv问题不考虑是因为比较负责,涉及每个面都相同还是去不同的uv,所以在此不做展开。

原文地址:https://www.cnblogs.com/llstart-new0201/p/12253697.html