Unity3D之Mesh(一)繪制三角形


前言:

Unity自帶幾種簡單的模型,如cube等;一般情況下,其余模型有3D建模軟件生成,以合適的文件格式導入unity中;而mesh(以我目前很粗淺的了解)的一般用途就是:對現有的模型進行變形,以達到各種奇幻酷炫的表現效果。

但是由於自己的項目需要,需要由數據(外部解釋stl文件獲得)按照特定情況以及要求實時地產生各種幾何模型,故需要用Mesh進行建模。所以開始研究學習Mesh。


一、引入

3D世界中任何的面都是由三角形繪制完成的,因為任何無規則的集合圖形都可以由三角形來組成。比如四邊形,無論是正四邊形還是無規則四邊形都可以由兩個三角形拼接而成。如下圖,模型上的一個個小網格就是Mesh,這些Mesh有不同的三維頂點(Vector3),共同組成了一個3D模型。


 

二、正文

知識點說明:

1.Mesh、MeshFilter、MeshRenderer關系整理

在Unity3D中創建一個Cube,在Inspector可以看到其中含有MeshFilter、MeshRenderer組件。

MeshFilter含有一個Public成員 Mesh。

在Mesh中存儲着三維模型的數據:vertices(頂點數據數組Vector3[])、triangles(三角形頂點索引數組,int[])、normals(法線向量數組,Vector3[])、uv(紋理坐標數組,Vector2[])。

2.

 Unity3D中Mesh的基本單位是三角形,故而從最基本最簡單的等腰三角形開始畫起。

 Mesh是Unity內的一個組件,稱為網格組件。

Mesh:是指模型的網格,建模就是建網格。細看Mesh,可以知道Mesh的主要屬性內容包括頂點坐標法線紋理坐標三角形繪制序列等其他有用屬性和功能。因此建網格,就是畫三角形;畫三角形就是定位三個點。

Mesh Filter:內包含一個Mesh組件,可以根據MeshFilter獲得模型網格的組件,也可以為MeshFilter設置Mesh內容。

Mesh Render:是用於把網格渲染出來的組件。MeshFilter的作用就是把Mesh扔給MeshRender將模型或者說是幾何體繪制顯示出來。 

它們之間的關系大概就是Unity中的對象就是GameObject,每個GameObject都可以有一個MeshFilter組件(也可以沒有),該組件又有Mesh屬性(這個一定有),而該屬性又有頂點坐標,法線等屬性。而如果GameObject里有MeshFilter,則必須要Mesh Renderer才能將此網格渲染出來,不然是看不見該網格的。


 

 Mesh的屬性

  • 頂點坐標(vertex)
  • 法線(normal)
  • 紋理坐標(uv)
  • 三角形序列(triangle)

頂點坐標:頂點坐標數組存放Mesh的每個頂點的空間坐標,假設某mesh有n個頂點,則vertex的size為n

法線:法線數組存放mesh每個頂點的法線,大小與頂點坐標對應,normal[i]對應頂點vertex[i]的法線

紋理坐標:它定義了圖片上每個點的位置的信息. 這些點與3D模型是相互聯系的, 以決定表面紋理貼圖的位置. UV就是將圖像上每一個點精確對應到模型物體的表面. uv[i]對應vertex[i]

三角形序列:每個mesh都由若干個三角形組成,而三角形的三個點就是頂點坐標里的點,三角形的數組的size = 三角形個數 * 3.     說白了:規定繪制的順序(點連接的順序)

例如:某mesh有四個頂點0,1,2,3,

V0(1, 1, 0),
V1(-1, 1, 0),
V2(1, -1, 0),
V3(-1, -1, 0)

那么它們可以組成這樣的一個網格,

tri[0] = ver[0],ver[3],ver[1],tri[1] = ver[0],ver[2],ver[3],

注意:三角形的頂點順序必須是順時針,順時針表示正面,逆時針表示背面,而unity3d在渲染時默認只渲染正面,背面是看不見的。

那么該三角形可以表示為:

tri  = new int[2 * 3]{0, 3, 1,   0, 2, 3};

如何要獲取第N個三角形對應的三個頂點坐標,則:v1 = tri[N*3 + 0], v2 = tri[N*3 + 1], v3 = tir[N*3 + 2]


參照的案例(配合上述的知識點)【此事例參照他人】

1.創建一個GameObject並添加MeshFilter以及MeshRender組件,並創建一個“CreateMesh.cs”腳本給它。

2.獲取該對象的filter組件,並創建一個mesh給它。

3.為該mesh設置屬性,這里先設置頂點,然后將三角形與頂點綁定

using UnityEngine;
using System.Collections;

public class CreateMesh : MonoBehaviour {

    private MeshFilter filter;
    private Mesh mesh;

    // Use this for initialization
    void Start () {
        // 獲取GameObject的Filter組件
        filter = GetComponent<MeshFilter>();
        // 並新建一個mesh給它
        mesh = new Mesh();
        filter.mesh = mesh;

        // 初始化網格
        InitMesh();
    }
    
    // Update is called once per frame
    void Update () {
    
    }

    /// <summary>
    /// Inits the mesh.
    /// </summary>
    void InitMesh()
    {
        mesh.name = "MyMesh";

        // 為網格創建頂點數組
        Vector3[] vertices = new Vector3[4]{
            new Vector3(1, 1, 0),
            new Vector3(-1, 1, 0),
            new Vector3(1, -1, 0),
            new Vector3(-1, -1, 0)
        };

        mesh.vertices = vertices;

        // 通過頂點為網格創建三角形
        int[] triangles = new int[2 * 3]{
            0, 3, 1,   0, 2, 3
        };

        mesh.triangles = triangles;
    }
}

效果如圖:

3.網格已經成功生成,接下來該給網格貼圖了,在Inspector視圖里選中Mesh Render,並拖一個材質給它,

Mesh Render是負責渲染的,將Mesh Filter里的mesh通過自身的Materials渲染出來。

設置完材質后,我們需要將紋理貼圖與網格頂點一一對應起來,這樣才能渲染出來。

// 為mesh設置紋理貼圖坐標
        Vector2[] uv = new Vector2[4]{
            new Vector2(1, 1),
            new Vector2(0, 1),
            new Vector2(1, 0),
            new Vector2(0, 0)
        };

        mesh.uv = uv;

 效果如圖:

4.mesh還有兩個重要的屬性,法線和顏色,這兩個我不是很懂,暫時沒加入,

不過看了下自帶的cube模型的mesh,每個頂點的法線好像就是設置為那個頂點所在的面的法線。

不過肯定不是這樣的,畢竟要是兩個不在同一面的面共有一個頂點,那就不成立了。


 

自己做的案例:(最簡單粗暴地顯示出一個三角形)

 1 using UnityEngine;
 2 using System.Collections;
 3 [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
 4 public class triangle_mesh : MonoBehaviour
 5 {
 6     /*
 7     creat a triangle by using Mesh 
 8      2016/11/19
 9                  ————Carl    
10     */
11 
12     void Start()
13     {
14         MeshFilter meshfilter = new MeshFilter();
15         meshfilter = GetComponent<MeshFilter>();
16         Mesh mesh = new Mesh();
17         Vector3[] vertices = new Vector3[3];
18         vertices[0] = new Vector3(0, 0, 0);
19         vertices[1] = new Vector3(0, 0, 1);
20         vertices[2] = new Vector3(1, 0, 0);
21         int[] tris = new int[3];
22         tris[0] = 0; tris[1] = 1; tris[2] = 2;
23         Vector2[] uvs = new Vector2[vertices.Length];
24         for (int i = 0; i < uvs.Length; i++)
25         {
26             uvs[i] = Vector2.zero;
27         }
28 
29         mesh.vertices = vertices;
30         mesh.triangles = tris;
31         mesh.uv = uvs;
32         meshfilter.mesh = mesh;
33     }
34 }

效果圖:

 

 

程序說明:

1)

 

 

2)

RequireComponent這一行,表示我們需要MeshRenderer和MeshFilter這兩個組件,當我們將TestTriangle的代碼掛在GameObject上的時候,會自動添加這兩個組件。而我們要移除MeshRenderer或MeshFilter的時候,編輯器就會提示不能移除。

ExecuteInEditMode表示會在編輯器模式下運行。

uv暫時我們用不到,所以全部設為零。在后面文章中將介紹uv的用法。



總結:

用Unity繪制三角形

首先,creat a gameobject

其次,掛在一個腳本,並且,添加 MeshRenderer,MeshFilter組件

再其次:給出Mesh的: mesh.vertices = vertices;//點 mesh.triangles = tris;//索引點 mesh.uv = uvs;//紋理

最后:meshfilter.mesh = mesh;//添加於MeshFilter組件



 

【歡迎轉載】

 轉載請表明出處: 樂學習


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM