Unity3D開發之建立mesh
阿新 • • 發佈:2019-02-17
之前寫過一篇部落格,當時主要介紹的自繪地形並建立地形,著重介紹頂點排序處理以及分割三角形問題。當時由於著急,忽略了一些問題。之前寫的建立mesh其實是有問題的,我只給mesh賦上頂點資訊,並沒有賦上法線資訊以及uv資訊。所以,本片部落格著重講下建立mesh過程。
首先我們需要獲取到頂點資訊,也就是組成這個mesh的所有三角形頂點資訊。這裡提醒下:一定不要省下那些重複頂點資訊。一定不要省下那些重複頂點資訊。一定不要省下那些重複頂點資訊。有的人發現一個頂點被兩次用到就在頂點陣列中只寫入一次,那樣會給我們後來的其他資訊賦值帶來很多的麻煩,所以千萬不要省。一個mesh由幾個三角形組成,然後就依次將每個三角形頂點寫入到頂點陣列中。
如下圖:我們要建立一個正方形mesh。
我們先將頂點資訊寫入進去,程式碼如下:
頂點資訊和索引是必須的,當沒有賦值法線方向陣列時,我們會發現mesh的光照資訊會有錯誤,而且不能顯示出來光影資訊,所以法線方向是必須要賦值的。下面說下可有也可無的uv資訊。//每個頂點的位置資訊 Vector3[] vertices = new[] {new Vector3(0,0,0),new Vector3(0,0,2), new Vector3(2, 0, 0) , new Vector3(2, 0,0), new Vector3(0, 0,2),new Vector3(2, 0, 2)}; //每個頂點的索引 int[] ints = new[] {0, 1, 2, 3, 4, 5}; //每個頂點的法線方向 Vector3[] normals = new[] {Vector3.up, Vector3.up, Vector3.up, Vector3.up, Vector3.up, Vector3.up};
這個折磨我很久。當我們想在mesh上貼我們想要的貼圖時,就必須要設定uv資訊了。程式碼如下:
標準的正方形uv資訊很好設定,每個點都是邊界值、而當我們設定不規則的多邊形時,我們就需要計算每個頂點然後去設定uv的值。我的方法就是獲取所有頂點中X,Y最大和最小值。然後求的X最大值和最小值的差以及Y最大值和最小值的差,這樣我們就固定出來了一個長方形的區域可以蓋住我們的不規則多邊形,然後我們計算每一個頂點的xy分量和對應分量最小值之差再除以對應分量的最大值與最小值之差。程式碼如下://uv資訊 Vector2[] uvs = new[] { new Vector2(0,0), new Vector2(0, 1), new Vector2(1, 0), new Vector2(1, 0), new Vector2(0, 1), new Vector2(1,1), }; m.uv = uvs;
for (int i = 0; i < newVerList.Count; i++)
{
ints[i] = i;
normals[i]=Vector3.up;
pos = newVerList[i];
_kx = (pos.x - _v[0]) / _v[2];
_ky = (pos.z - _v[1]) / _v[2];
uvs[i]=(new Vector2(_kx, _ky));
}
private Vector3 getVector3(Vector3[] vs)
{
float ymin = vs[0].z;
float ymax = vs[0].z;
float xmin= vs[0].x;
float xmax = vs[0].x;
for (int i =1; i < vs.Length; i++)
{
if (ymin > vs[i].z)
{
ymin = vs[i].z;
}
if (ymax < vs[i].z)
{
ymax = vs[i].z;
}
if (xmin > vs[i].x)
{
xmin = vs[i].x;
}
if (xmax < vs[i].x)
{
xmax = vs[i].x;
}
}
//Debug.Log("xmin+"+xmin + "+xmax+"+xmax + "+ymin+"+ymin +"+ymax+"+ymax);
return new Vector3(xmin,ymin,xmax-xmin>ymax-ymin?xmax-xmin:ymax-ymin);
}
然後我們就將每個頂點所求的比例值賦值到每個頂點的uv陣列中。這樣一張貼圖就可以無縫的顯示在多邊形mesh上。下面是demo的完整程式碼。
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class CreatMyMesh : MonoBehaviour {
// Use this for initialization
void Start ()
{
//每個頂點的位置資訊
Vector3[] vertices = new[] {new Vector3(0,0,0),new Vector3(0,0,2), new Vector3(2, 0, 0) , new Vector3(2, 0,
0), new Vector3(0, 0,2),new Vector3(2, 0, 2)};
//每個頂點的索引
int[] ints = new[] {0, 1, 2, 3, 4, 5};
//每個頂點的法線方向
Vector3[] normals = new[] {Vector3.up, Vector3.up, Vector3.up, Vector3.up, Vector3.up, Vector3.up};
//uv資訊
Vector2[] uvs = new[]
{
new Vector2(0,0), new Vector2(0, 1), new Vector2(1, 0), new Vector2(1, 0), new Vector2(0, 1), new Vector2(1,1),
};
Mesh m = new Mesh();
m.vertices = vertices;
m.triangles = ints;
m.normals = normals;
m.uv = uvs;
GetComponent<MeshFilter>().mesh = m;
}
}
以上就是我在開發中解決的辦法。希望對你有幫助。