【Unity】Mesh网格编程(二)流体

来源:互联网 发布:xbox360淘宝店推荐 编辑:程序博客网 时间:2024/04/30 02:54

通过Mesh网格随Sin函数实时变化模拟液体的流动,从而达到动态水的效果。


原文:

Mesh网格编程(一) 流体

http://blog.csdn.net/qq_18408937/article/details/44161229

by 涅凡尘


对,你没有看错。这是本博客的一个系列,但同时也是一篇转载。

原文已经做得很棒了!不做重复工作,直接转入本系列中。

也欢迎大家支持这位技术博客新人和数学奇才,多粉多浏览。


Mesh网格编程(一) 流体水

通过Mesh网格随Sin函数实时变化模拟液体的流动,从而达到动态水的效果。

效果图:

Mesh网格编程步骤:

一:确定数量

确定该几何图形应有多少个三角形面,顶点坐标、顶点序列、UV贴图、法线向量皆为三角形面数的三倍。

二:根据三角形面确定顶点坐标

这里我习惯把一个面的顶点确定好之后再去找下一个面,这样做可以是法线和顶点序列确定起来很容易。但是要注意的是在确定顶点时要按照顺时针顺序确定,否则会导致三角形面相反。

三:确定法线

法线大致分为两种:
其一是棱角分明的几何体,这种几何体的法线可以用确定好的顶点坐标两两相减,得到的向量做叉乘并赋值给三个顶点上的法线。
其二是圆滑的几何体,这种几何体需要求出该点在曲面上的切线,从而确定垂直于切线的法线。如果是圆形。可以使用顶点减圆心所得的向量。
此外,求得的法线尽量单位化,否则可能出现一个面上的颜色不同。

四:确定顶点序列

若三角形顶点按照面数去确定,顶点序列就会变得非常简单,按顺序赋值即可。

五:确定UV贴图

根据所做几何体的不同,贴图左边也会有所改变,并不固定。

六:创建网格


实现代码如下:

[csharp] view plaincopy
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class Water : MonoBehaviour {  
  5.   
  6.     Mesh mesh;  
  7.   
  8.     public int tier = 10;           //长度分段  
  9.     private float length = 10;      //长  
  10.     private int width = 3;          //宽  
  11.     private int hight = 10;         //高  
  12.   
  13.     private Vector3[] vs;           //顶点坐标  
  14.     private int[] ts;               //顶点序列  
  15.     private Vector2[] newUVs;       //UV贴图  
  16.     private Vector3[] newNormals;   //法线  
  17.       
  18.     void Update () {  
  19.   
  20.         int temp = ((tier + 1) * 8 + 4) * 3;    //确定顶点数量  
  21.   
  22.         vs = new Vector3[temp];  
  23.         ts = new int[temp];  
  24.         newUVs = new Vector2[temp];  
  25.         newNormals = new Vector3[temp];  
  26.   
  27.         float dis = 2 * Mathf.PI / tier;        //两段之差的横坐标  
  28.   
  29.         int count = 0;  
  30.         for (int i = 0; i < tier; i++) {  
  31.   
  32.             float pos1 = i * length / tier - length / 2;  
  33.             float pos2 = (i + 1) * length / tier - length / 2;  
  34.             //顶面顶点坐标  
  35.             vs[count] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), width);  
  36.             vs[count + 1] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), -width);  
  37.             vs[count + 2] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), -width);  
  38.   
  39.             vs[count + 3] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), width);  
  40.             vs[count + 4] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), width);  
  41.             vs[count + 5] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), -width);  
  42.             //顶面法线  
  43.             newNormals[count] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + i * dis), 0));  
  44.             newNormals[count + 1] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + (i + 1) * dis), 0));  
  45.             newNormals[count + 2] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + i * dis), 0));  
  46.                   
  47.             newNormals[count + 3] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + i * dis), 0));  
  48.             newNormals[count + 4] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + (i + 1) * dis), 0));  
  49.             newNormals[count + 5] = Vector3.Normalize(new Vector3(1,Mathf.Cos(Time.time + (i + 1) * dis), 0));  
  50.   
  51.             //前面顶点坐标  
  52.             vs[count + 6] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), -width);  
  53.             vs[count + 7] = new Vector3(pos2,-hight, -width);  
  54.             vs[count + 8] = new Vector3(pos1,-hight, -width);  
  55.   
  56.             vs[count + 9] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), -width);  
  57.             vs[count + 10] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), -width);  
  58.             vs[count + 11] = new Vector3(pos2,-hight, -width);  
  59.             //前面法线  
  60.             for (int j = 0; j < 6; j++) {  
  61.                 newNormals[count + 6 + j] = Vector3.back;  
  62.             }  
  63.             //后面顶点坐标  
  64.             vs[count + 12] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), width);  
  65.             vs[count + 13] = new Vector3(pos1,-hight, width);  
  66.             vs[count + 14] = new Vector3(pos2,-hight, width);  
  67.               
  68.             vs[count + 15] = new Vector3(pos1,Mathf.Sin(Time.time + i * dis), width);  
  69.             vs[count + 16] = new Vector3(pos2,-hight, width);  
  70.             vs[count + 17] = new Vector3(pos2,Mathf.Sin(Time.time + (i + 1) * dis), width);  
  71.             //后面法线  
  72.             for (int j = 0; j < 6; j++) {  
  73.                 newNormals[count + 12 + j] = Vector3.forward;  
  74.             }  
  75.             //下面顶点坐标  
  76.             vs[count + 18] = new Vector3(pos1,-hight, width);  
  77.             vs[count + 19] = new Vector3(pos1,-hight, -width);  
  78.             vs[count + 20] = new Vector3(pos2,-hight, -width);  
  79.   
  80.             vs[count + 21] = new Vector3(pos1,-hight, width);  
  81.             vs[count + 22] = new Vector3(pos2,-hight, -width);  
  82.             vs[count + 23] = new Vector3(pos2,-hight, width);  
  83.             //下面法线  
  84.             for (int j = 0; j < 6; j++) {  
  85.                 newNormals[count + 18 + j] = Vector3.down;  
  86.             }  
  87.   
  88.             count += 24;  
  89.         }  
  90.   
  91.         //两侧顶点坐标及法线  
  92.         vs [vs.Length - 12] = new Vector3 (-length / 2, Mathf.Sin (Time.time), width);  
  93.         vs [vs.Length - 11] = new Vector3 (-length / 2, -hight, -width);  
  94.         vs [vs.Length - 10] = new Vector3 (-length / 2, -hight, width);  
  95.   
  96.         vs [vs.Length - 9] = new Vector3 (-length / 2, Mathf.Sin (Time.time), width);  
  97.         vs [vs.Length - 8] = new Vector3 (-length / 2, Mathf.Sin (Time.time), -width);  
  98.         vs [vs.Length - 7] = new Vector3 (-length / 2, -hight, -width);  
  99.   
  100.         for (int j = 0; j < 6; j++) {  
  101.             newNormals[vs.Length - 12 + j] = Vector3.left;  
  102.         }  
  103.   
  104.         vs [vs.Length - 6] = new Vector3 (length / 2, Mathf.Sin (Time.time + tier * dis), width);  
  105.         vs [vs.Length - 5] = new Vector3 (length / 2, -hight, width);  
  106.         vs [vs.Length - 4] = new Vector3 (length / 2, -hight, -width);  
  107.   
  108.         vs [vs.Length - 3] = new Vector3 (length / 2, Mathf.Sin (Time.time + tier * dis), width);  
  109.         vs [vs.Length - 2] = new Vector3 (length / 2, -hight, -width);  
  110.         vs [vs.Length - 1] = new Vector3 (length / 2, Mathf.Sin (Time.time + tier * dis), -width);  
  111.   
  112.         for (int j = 0; j < 6; j++) {  
  113.             newNormals[vs.Length - 6 + j] = Vector3.right;  
  114.         }  
  115.   
  116.         for (int i = 0; i < ts.Length; i++) {    //顶点序列赋值  
  117.             ts[i] = i;  
  118.         }  
  119.   
  120.         mesh = new Mesh();  
  121.         GetComponent<MeshFilter>().mesh = mesh;  
  122.         mesh.vertices = vs;  
  123.         mesh.uv = newUVs;  
  124.         mesh.triangles = ts;  
  125.         mesh.normals = newNormals;  
  126.     }  
  127. }  

注:波浪上方的面为曲面,故使用切线求法线。其他面很有规则,并没有使用叉乘的方法。
几何体没有使用UV贴图,newUVs没有赋值。


0 0
原创粉丝点击