1. 程式人生 > >Mesh網格程式設計(四) 正6面體

Mesh網格程式設計(四) 正6面體

前兩期轉載了兩個建立流水體和正12面體的文章,今天一個學生問我怎麼建立一個立方體,我的第一印象,Unity自帶的有一個GameObject.CreatePrimitive(PrimitiveType.Cube);方法。但是顯然現在他是想利用網格程式設計建立一個立方體,而不是這個方法。

首先我們分析下原理:

1.所有模型都是由一個一個三角形面構成。那麼我們先來建立一個三角形:

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour
{
    void Start()
    {
        gameObject.AddComponent<MeshFilter>();
        gameObject.AddComponent<MeshRenderer>();
        Mesh mesh = GetComponent<MeshFilter>().mesh;
        mesh.Clear();
        mesh.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0) };
        mesh.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1) };
        mesh.triangles = new int[] { 0, 1, 2 };
    }
}


其中的mesh.trangles就是這個三角形,為什麼是3個int型別的數呢?因為trangles是一個包含頂點陣列索引的三角形列表。

因此這個陣列的的大小必須是3的倍數,頂點可以通過簡單的索引同一頂點來共享。

建議先賦值頂點陣列後再賦值三角形陣列,避免陣列越界的錯誤。

2.上面有了一個三角形的網格建立,現在咱們嘗試建一個正方形。

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour
{
    void Start()
    {
        gameObject.AddComponent<MeshFilter>();
        gameObject.AddComponent<MeshRenderer>();
        Mesh mesh = GetComponent<MeshFilter>().mesh;
        mesh.Clear();
        mesh.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0), new Vector3(1, 0, 0) };
        mesh.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1) };
        mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };
    }
}
我們發現這個程式碼,就比三角形多了一個頂點和一個三角形,我們輸出圖片後就明白三角形為什麼這麼設定了。



兩個三角形的頂點,根據三角形的位置來劃分。

3.有了前面兩個基礎了,下面我們來建立一個立方體(六面體)。

好在六面體是一個非常規則的圖形,我們可以計算出,每個定點的位置,共8個定點。但是前面提到了,每個三角形被3個定點公用,我們一個頂點座標需要有3個,分別被3個三角形使用。這樣這個三角形的陣列設定起來就比較方便了。下面看程式碼:

using UnityEngine;
using UnityEditor;

public class BoxEditor : Editor
{
    static Mesh mesh;            // 網格
    static Vector3[] Vs;         // 模型頂點座標陣列
    static int[] Ts;             // 三角形的點序列
    static float lenght = 1f;

    [MenuItem("GameObject/Create Other/Box")]
    static void CreateRegular()
    {
        lenght /= 2f;
        //網格定點,8個頂點,每個定點被3個三角形公用,共24個定點
        Vs = new Vector3[]{
            new Vector3(lenght, -lenght, lenght),
            new Vector3(-lenght, -lenght, lenght),
            new Vector3(lenght, lenght, lenght),
            new Vector3(-lenght, lenght, lenght),
            new Vector3(lenght, lenght, -lenght),
            new Vector3(-lenght, lenght, -lenght),
            new Vector3(lenght, -lenght, -lenght),
            new Vector3(-lenght, -lenght, -lenght),
            new Vector3(lenght, lenght, lenght),
            new Vector3(-lenght, lenght, lenght),
            new Vector3(lenght, lenght, -lenght),
            new Vector3(-lenght, lenght, -lenght),
            new Vector3(lenght, -lenght, -lenght),
            new Vector3(lenght, -lenght, lenght),
            new Vector3(-lenght, -lenght, lenght),
            new Vector3(-lenght, -lenght, -lenght),
            new Vector3(-lenght, -lenght, lenght),
            new Vector3(-lenght, lenght, lenght),
            new Vector3(-lenght, lenght, -lenght),
            new Vector3(-lenght, -lenght, -lenght),
            new Vector3(lenght, -lenght, -lenght),
            new Vector3(lenght, lenght, -lenght),
            new Vector3(lenght, lenght, lenght),
            new Vector3(lenght, -lenght, lenght) };

        //三角形的面,(頂點索引構成,每3個頂點一個面,)
        Ts = new int[] { 
            0, 2, 3,
            0, 3, 1,
            8, 4, 5,
            8, 5, 9,
            10, 6, 7,
            10, 7, 11,
            12, 13, 14,
            12, 14, 15,
            16, 17, 18,
            16, 18, 19,
            20, 21, 22,
            20, 22, 23, };
        
        // 呼叫建立物件函式
        CreateObjectByMesh("Box");
    }

    // 建立物件函式(這個功能提出來,方便以後擴充套件)
    static void CreateObjectByMesh(string name)
    {
        GameObject regular = new GameObject();  // 建立遊戲物件
        regular.name = name;                    // 根據引數命名
        regular.AddComponent<MeshFilter>();     // 新增MeshFilter元件
        regular.AddComponent<MeshRenderer>();   // 新增MeshRenderer元件

        mesh = new Mesh();                      // 建立網格
        mesh.vertices = Vs;                     // 網格的頂點
        mesh.triangles = Ts;                    // 網格的三角形
        regular.GetComponent<MeshFilter>().mesh = mesh; // 新增網格
    }
}

這是一個編輯器指令碼,寫完後放到你的Editor資料夾下,然後選擇Unity上面的選單欄,GameObject->Create Other->Box就行了。

然後賦值上材質,如下圖所示: