【Unity】Mesh網格程式設計(二)流體
阿新 • • 發佈:2019-02-17
通過Mesh網格隨Sin函式實時變化模擬液體的流動,從而達到動態水的效果。
原文:
by 涅凡塵
對,你沒有看錯。這是本部落格的一個系列,但同時也是一篇轉載。
原文已經做得很棒了!不做重複工作,直接轉入本系列中。
也歡迎大家支援這位技術部落格新人和數學奇才,多粉多瀏覽。
Mesh網格程式設計(一) 流體水
通過Mesh網格隨Sin函式實時變化模擬液體的流動,從而達到動態水的效果。
效果圖:
Mesh網格程式設計步驟:
一:確定數量
確定該幾何圖形應有多少個三角形面,頂點座標、頂點序列、UV貼圖、法線向量皆為三角形面數的三倍。二:根據三角形面確定頂點座標
這裡我習慣把一個面的頂點確定好之後再去找下一個面,這樣做可以是法線和頂點序列確定起來很容易。但是要注意的是在確定頂點時要按照順時針順序確定,否則會導致三角形面相反。三:確定法線
四:確定頂點序列
若三角形頂點按照面數去確定,頂點序列就會變得非常簡單,按順序賦值即可。五:確定UV貼圖
根據所做幾何體的不同,貼圖左邊也會有所改變,並不固定。六:建立網格
實現程式碼如下:
- using UnityEngine;
-
using System.Collections;
- publicclass Water : MonoBehaviour {
- Mesh mesh;
- publicint tier = 10; //長度分段
- privatefloat length = 10; //長
- privateint width = 3; //寬
- privateint hight = 10; //高
- private Vector3[] vs; //頂點座標
- privateint[] ts; //頂點序列
-
private Vector2[] newUVs;
- private Vector3[] newNormals; //法線
- void Update () {
- int temp = ((tier + 1) * 8 + 4) * 3; //確定頂點數量
- vs = new Vector3[temp];
- ts = newint[temp];
- newUVs = new Vector2[temp];
- newNormals = new Vector3[temp];
- float dis = 2 * Mathf.PI / tier; //兩段之差的橫座標
- int count = 0;
- for (int i = 0; i < tier; i++) {
- float pos1 = i * length / tier - length / 2;
- float pos2 = (i + 1) * length / tier - length / 2;
- //頂面頂點座標
- vs[count] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), width);
- vs[count + 1] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), -width);
- vs[count + 2] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), -width);
- vs[count + 3] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), width);
- vs[count + 4] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), width);
- vs[count + 5] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), -width);
- //頂面法線
- newNormals[count] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + i * dis), 0));
- newNormals[count + 1] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + (i + 1) * dis), 0));
- newNormals[count + 2] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + i * dis), 0));
- newNormals[count + 3] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + i * dis), 0));
- newNormals[count + 4] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + (i + 1) * dis), 0));
- newNormals[count + 5] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + (i + 1) * dis), 0));
- //前面頂點座標
- vs[count + 6] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), -width);
- vs[count + 7] = new Vector3(pos2,-hight, -width);
- vs[count + 8] = new Vector3(pos1,-hight, -width);
- vs[count + 9] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), -width);
- vs[count + 10] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), -width);
- vs[count + 11] = new Vector3(pos2,-hight, -width);
- //前面法線
- for (int j = 0; j < 6; j++) {
- newNormals[count + 6 + j] = Vector3.back;
- }
- //後面頂點座標
- vs[count + 12] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), width);
- vs[count + 13] = new Vector3(pos1,-hight, width);
- vs[count + 14] = new Vector3(pos2,-hight, width);
- vs[count + 15] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), width);
- vs[count + 16] = new Vector3(pos2,-hight, width);
- vs[count + 17] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), width);
- //後面法線
- for (int j = 0; j < 6; j++) {
- newNormals[count + 12 + j] = Vector3.forward;
- }
- //下面頂點座標
- vs[count + 18] = new Vector3(pos1,-hight, width);
- vs[count + 19] = new Vector3(pos1,-hight, -width);
- vs[count + 20] = new Vector3(pos2,-hight, -width);
- vs[count + 21] = new Vector3(pos1,-hight, width);
- vs[count + 22] = new Vector3(pos2,-hight, -width);
- vs[count + 23] = new Vector3(pos2,-hight, width);
- //下面法線
- for (int j = 0; j < 6; j++) {
- newNormals[count + 18 + j] = Vector3.down;
- }
- count += 24;
- }
- //兩側頂點座標及法線
- vs [vs.Length - 12] = new Vector3 (-length / 2, Mathf.Sin (Time.time), width);
- vs [vs.Length - 11] = new Vector3 (-length / 2, -hight, -width);
- vs [vs.Length - 10] = new Vector3 (-length / 2, -hight, width);
- vs [vs.Length - 9] = new Vector3 (-length / 2, Mathf.Sin (Time.time), width);
- vs [vs.Length - 8] = new Vector3 (-length / 2, Mathf.Sin (Time.time), -width);
- vs [vs.Length - 7] = new Vector3 (-length / 2, -hight, -width);
- for (int j = 0; j < 6; j++) {
- newNormals[vs.Length - 12 + j] = Vector3.left;
- }
- vs [vs.Length - 6] = new Vector3 (length / 2, Mathf.Sin (Time.time + tier * dis), width);
- vs [vs.Length - 5] = new Vector3 (length / 2, -hight, width);
- vs [vs.Length - 4] = new Vector3 (length / 2, -hight, -width);
- vs [vs.Length - 3] = new Vector3 (length / 2, Mathf.Sin (Time.time + tier * dis), width);
- vs [vs.Length - 2] = new Vector3 (length / 2, -hight, -width);
- vs [vs.Length - 1] = new Vector3 (length / 2, Mathf.Sin (Time.time + tier * dis), -width);
- for (int j = 0; j < 6; j++) {
- newNormals[vs.Length - 6 + j] = Vector3.right;
- }
- for (int i = 0; i < ts.Length; i++) { //頂點序列賦值
- ts[i] = i;
- }
- mesh = new Mesh();
- GetComponent<MeshFilter>().mesh = mesh;
- mesh.vertices = vs;
- mesh.uv = newUVs;
- mesh.triangles = ts;
- mesh.normals = newNormals;
- }
- }