2016年5月21日 星期六

2D ellipse mesh in Unity

這篇文章講的是在 Unity 中以 script 建立 2D 橢圓。


Project view 中是有一個 Circle Sprite,

但那是一個 sprite,實際上仍是矩形,裡面放一個圓形的圖案而已,不是我要的。

一個真正的 2D ellipse mesh 它的外圍形狀是橢圓的,我們在實做時,把多個頂點繞著圓心一圈組成。示意圖配合公式,像是這樣:

只要在code裡面產生很多三角形(紅色那些三角形),繞一圈,就可以組成一個橢圓。


Unity 裡面,每個物體都會由多個 Mesh 組成,而每個 Mesh 再由多個三角形組成。每個三角形有三個頂點,每個頂點上有一些屬性,像是座標、UV、法線向量...。不過這篇文章只示範產生座標的方法,而法線讓 unity 自動計算,至於 UV 這個用來配置材質的東西,以後再說。


在兜橢圓時,三角形的數量越多,看起來就會越圓。底下這個是5個三角形組成的橢圓:

是不像橢圓,但比較好解釋,因為上面的藍色線的方向是有意義的。Unity 中的三角形,它的三個頂點在連起來時,順序必須是順時針方向,否則看不到。如果你畫了三角形卻看不到,很可能Camera 照到它的背面了,可以去三角形的背面看看。


可動的code:
 1 using UnityEngine;
 2 using UnityEngine.UI;
 3 using System.Collections;
 4 using System.Collections.Generic;
 5 using System;
 6 using Random = UnityEngine.Random;
 7 
 8 using UnityEngine.Events;
 9 using UnityEngine.EventSystems;
10 
11 
12 public class test : MonoBehaviour
13 {
14   void Start ()
15   {
16     Ellipse2D ellipse1 = new Ellipse2D (0, 0, 0, 1, 1);
17     Ellipse2D ellipse2 = new Ellipse2D (4, 0, 0, 2, 3);
18     Ellipse2D ellipse3 = new Ellipse2D (2, 5, 0, 3, 2);
19   }
20 }
21 
22 
23 public class Ellipse2D
24 {
25   public GameObject gameObject;
26 
27   public Ellipse2D (
28     float   x,
29     float   y,
30     float   z,
31     float   semiMajor,
32     float   semiMinor
33   )
34   {
35     gameObject = new GameObject ("Ellipse2D");
36 
37     Vector3 center = new Vector3 (x, y, z);
38     gameObject.transform.localPosition = center;
39 
40     Renderer renderer = gameObject.AddComponent<MeshRenderer> ();
41     renderer.material = new Material (Shader.Find ("Diffuse"));
42 
43     // 建立 mesh. 一個 mesh 上可以有多個三角形
44     Mesh mesh = new Mesh ();
45 
46     // 定義每個 ellipse 上由 30 個三角形構成
47     int triangleCount = 30; // 10
48 
49     float dTh = (2 * Mathf.PI / triangleCount);
50 
51     // 存放頂點
52     Vector3[] vertices = new Vector3[triangleCount * 3];
53 
54     // 每個 for index 會計算一個三角形中的三個頂點座標
55     for (int index = 0; index < triangleCount; index++) {
56 
57       // triangle vertex 1
58       vertices [index * 3] = new Vector3 (0, 0, 0);
59 
60       // triangle vertex 2
61       float th1 = dTh * (index + 1);
62       vertices [index * 3 + 1] = new Vector3 (semiMajor * Mathf.Cos (th1), semiMinor * Mathf.Sin (th1), 0);
63 
64       // triangle vertex 3
65       float th2 = dTh * (index);
66       vertices [index * 3 + 2] = new Vector3 (semiMajor * Mathf.Cos (th2), semiMinor * Mathf.Sin (th2), 0);
67     }
68 
69     // 蒐集所有頂點給 mesh
70     mesh.vertices = vertices;
71 
72     // 指定三角形的繞法
73     int[] triangles = new int[triangleCount * 3];
74     for (int i = 0; i < triangleCount * 3; i++) {
75       triangles [i] = i;
76     }
77 
78     mesh.triangles = triangles;
79 
80     // 自動計算法線
81     mesh.RecalculateNormals ();
82     mesh.RecalculateBounds ();
83     mesh.Optimize ();
84 
85     // 最後對物件添上 MeshFilter component, 指定 mesh 給他。
86     MeshFilter mf = gameObject.AddComponent<MeshFilter> ();
87     mf.mesh = mesh;
88   }
89 }
90 

圖看起來像這樣:




Reference:
http://docs.unity3d.com/ScriptReference/Mesh.html












沒有留言:

張貼留言