前言:
從現在開始,終於感覺進入一點點正題了!動態創建三維立體模型mesh!依然從簡單入手:長方體。
一、基本思路
由於是創建長方體mesh,由之前的研究得知,兩個數據必須要有,即:頂點的數據:vertices與索引的三角形(即負責管理每個三角形的三點的索引順序):triangles。長方體:一般會得知:長寬高;即今天我們由長寬高為參數得到vertices與triangles。
二、基本程序框架
創建一個empty的gameobject,掛在腳本。
由基本思路可得基本框架,之后,實現函數功能即可;
1 using UnityEngine; 2 3 [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))] 4 public class cube_mesh : MonoBehaviour 5 { 6 public float Length = 5; //長方體的長 7 public float Width = 6; //長方體的寬 8 public float Heigth = 7; //長方體的高 9 private MeshFilter meshFilter; 10 11 void Start() 12 { 13 meshFilter = GetComponent<MeshFilter>(); 14 meshFilter.mesh = CreateMesh(Length, Width, Heigth); 15 } 16 17 Mesh CreateMesh(float length, float width, float heigth) 18 { 19 //vertices(頂點、必須): 20 //......... 21 22 //triangles(索引三角形、必須): 23 //......... 24 25 //uv: 26 //......... 27 28 //負載屬性與mesh 29 Mesh mesh = new Mesh(); 30 //......... 31 return mesh; 32 } 33 }

三、繪制函數的實現以及整個程序代碼
1 using UnityEngine; 2 3 [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))] 4 public class cube_mesh : MonoBehaviour 5 { 6 public float Length = 5; //長方體的長 7 public float Width = 6; //長方體的寬 8 public float Heigth = 7; //長方體的高 9 private MeshFilter meshFilter; 10 11 void Start() 12 { 13 meshFilter = GetComponent<MeshFilter>(); 14 meshFilter.mesh = CreateMesh(Length, Width, Heigth); 15 } 16 17 Mesh CreateMesh(float length, float width, float heigth) 18 { 19 20 //vertices(頂點、必須): 21 int vertices_count = 4*6; //頂點數(每個面4個點,六個面) 22 Vector3[] vertices = new Vector3[vertices_count]; 23 vertices[0] = new Vector3(0, 0, 0); //前面的左下角的點 24 vertices[1] = new Vector3(0, heigth, 0); //前面的左上角的點 25 vertices[2] = new Vector3(length, 0, 0); //前面的右下角的點 26 vertices[3] = new Vector3(length, heigth, 0); //前面的右上角的點 27 28 vertices[4] = new Vector3(length, 0, width); //后面的右下角的點 29 vertices[5] = new Vector3(length, heigth, width); //后面的右上角的點 30 vertices[6] = new Vector3(0, 0, width); //后面的左下角的點 31 vertices[7] = new Vector3(0, heigth, width); //后面的左上角的點 32 33 vertices[8] = vertices[6]; //左 34 vertices[9] = vertices[7]; 35 vertices[10] = vertices[0]; 36 vertices[11] = vertices[1]; 37 38 vertices[12] = vertices[2]; //右 39 vertices[13] = vertices[3]; 40 vertices[14] = vertices[4]; 41 vertices[15] = vertices[5]; 42 43 vertices[16] = vertices[1]; //上 44 vertices[17] = vertices[7]; 45 vertices[18] = vertices[3]; 46 vertices[19] = vertices[5]; 47 48 vertices[20] = vertices[2]; //下 49 vertices[21] = vertices[4]; 50 vertices[22] = vertices[0]; 51 vertices[23] = vertices[6]; 52 53 54 //triangles(索引三角形、必須): 55 int 分割三角形數 = 6 * 2; 56 int triangles_cout = 分割三角形數 * 3; //索引三角形的索引點個數 57 int[] triangles = new int [triangles_cout]; //索引三角形數組 58 for(int i=0,vi=0;i< triangles_cout;i+=6,vi+=4) 59 { 60 triangles[i] = vi; 61 triangles[i+1] = vi+1; 62 triangles[i+2] = vi+2; 63 64 triangles[i+3] = vi+3; 65 triangles[i+4] = vi+2; 66 triangles[i+5] = vi+1; 67 68 } 69 70 //uv: 71 //......... 72 73 //負載屬性與mesh 74 Mesh mesh = new Mesh(); 75 mesh.vertices = vertices; 76 mesh.triangles = triangles; 77 return mesh; 78 } 79 }
四、效果圖

五、其他相關的說明
1、冗余的頂點坐標
正方體6個面,每個面由2個三角形組成,所以共需要36個三角形頂點索引。但是正方體只有8個頂點,為什么需要24個頂點坐標數據呢?
答案是:Unity3D的Mesh.triangles是三角形索引數組,不僅依靠這個索引值索引三角形頂點坐標,而且索引紋理坐標,索引法線向量。即正方體的每個頂點都參與了3個平面,而這3個平面的法線向量是不同的,該頂點在渲染這3個平面的時候需要索引到不同的法線向量。而由於頂點坐標和法線向量是由同一個索引值triangles[Index]取得的,例如,根據vertices[0],vertices[10],vertices[22]在vertices中索引到的頂點都為(0,0,0),但是在normals中索引到的法向量值各不相同。這就決定了在正方體中一個頂點,需要有3份存儲。(如果你需要創建其它模型,需要根據實際情況決定頂點坐標的冗余度。實質上頂點坐標的冗余正是方便了法線坐標、紋理坐標的存取。)
2、三角形的渲染
准則:三角形有兩面,正面可見,背面不可見。三角形的渲染順序與三角形的正面法線呈左手螺旋定則。
這就決定了,如果我們需要渲染如下一個正方形面,那么就需要保證組成這個正方形的兩個小三角形的正面法線都是指向屏幕外的。

程序中的頂點順序為,三角形1: 0--->1--->2,三角形2:3--->2--->1 。
【歡迎轉載】
轉載請表明出處: 樂學習
