unity中Mesh網格程式設計
上圖是效果
一.關於mesh的意義
有了mesh網格,物體才能被渲染出來。
(1)mesh中包含頂點,
mesh.vertices
(2)頂點對應的uv(一張圖的uv左下角00,右上角11)
mesh.uv
(3)指定每個三角面對應的頂點位置(順時針方向culling back:預設不繪製背面)
mesh.triangles
(4)切線資訊
mesh.tangents
(5)法線資訊
mesh.normals
還有其它就不再說了,這裡主要是 頂點“veticles”,“uv”, 三角面“triangles”!!!
二.一個物體的正常渲染流程:
頂點座標 -》頂點對應的UV座標-》三角面對應的頂點位置
三.設定頂點的座標和順序可以多種多樣,但是條條大路通羅馬
例如:一個長方體:
設定頂點座標的方式:從上往下 從左往右 等
怎麼從0到1繪製一個簡單的長方形有很多教程,解釋的很清楚mesh程式設計入門精講
有兩個函式注意一下:
(1)重置法線垂直於當前的三角面
mesh.RecaculateNormals()
(2)將當前mesh,拆分成3個submesh
mesh.submeshCount = 3
mesh.SetTriangles(trianglesX, 0);
mesh.SetTriangles(trianglesY, 1);
mesh.SetTriangles(trianglesZ, 2);
並且 MeshRender中的Materials中的 第一個material對應渲染第一個submesh;第二個material對應渲染第二個;。。。。
四介紹繪製一個立方體的思路:
(1)計算頂點的個數:
//三個面的交點
int conerVerticles = 8;
// 兩個面的交點
int edgeVerticles = (xSize + ySize + zSize - 3) * 4;
// 上中下 三個面的點 (共6個面,所以要乘以2)
int faceVerticles = ((xSize - 1) * (ySize - 1) + (xSize - 1) * (zSize - 1) + (ySize - 1) * (zSize - 1)) * 2;
// 總頂點數量
int totalVerticles = conerVerticles + edgeVerticles + faceVerticles;
Vector3[] veticles = new Vector3[totalVerticles];
(2)在形成三角形的時需要用到三角形頂點的個數:
有n個四邊形,那麼總的三角形頂點數目: 4*n
//一共多少四邊形
int quads = (xSize * zSize + xSize * ySize + zSize * ySize) * 2;
// 三角面的頂點數
int totalCount = quads * 6;
int[] triangles = new int[totalCount];
(3)計算下一個triangles的索引:
// 返回值是 :下一個triangles的索引
static int SetQuad(int[]triangles,int t,int v00,int v10,int v01,int v11)
{
triangles[t] = v00;
triangles[t + 1] = triangles[t+4] = v01;
triangles[t + 2] = triangles[t+3] = v10;
triangles[t + 5] = v11;
return t + 6;
}
(4)其它的就沒有可講的了,都是如何拼接三角形形成mesh。順序和方法比較多。。思想都是一樣的。
下面附詳細程式碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class SplittingMesh : MonoBehaviour
{
public int xSize, ySize, zSize;
public int Roundness;
private Mesh mesh;
private Vector3[] vertices;
private Vector3[] normals;
private Color32[] CubeUV;
void Start()
{
GenerateVertices();
StartCoroutine(GenerateTriangles());
}
/// <summary>
/// 生成頂點
/// </summary>
void GenerateVertices()
{
GetComponent<MeshFilter>().mesh = mesh = new Mesh();
mesh.name = "Procedural Cube ";
int cornerVertices = 8; //八個角 八個頂點
int edgeVertices = (xSize +ySize +zSize -3)*4; //不考慮頂點公用的話 應該是 (xSize+ySize+zSize +1)*4
int faceVertices = (
(xSize-1)*(ySize-1)+
(xSize-1)*(zSize-1)+
(ySize-1)*(zSize-1)
)*2;
int vCount = cornerVertices + edgeVertices + faceVertices;
vertices = new Vector3[vCount];
normals = new Vector3[vertices.Length];
CubeUV = new Color32[vertices.Length];
int v = 0;
//賦予前後左右四個面頂點
for (int y = 0; y <=ySize; y++)
{
//前面
for (int x = 0; x <= xSize; x++)
{
SetVertex(v++, x, y, 0);
}
//右面 一開始 因為上面已經把最後一個點 公共頂點繪製完成
for (int z = 1; z <= zSize; z++)
{
SetVertex(v++, xSize, y, z);
}
//後面
for (int x = xSize - 1; x >= 0; x--)
{
SetVertex(v++, x, y, zSize);
}
//左面
for (int z = zSize - 1; z > 0; z--)
{
SetVertex(v++, 0, y, z);
}
}
//賦予上面頂點
for (int z = 1; z < zSize; z++)
{
for (int x = 1; x < xSize; x++)
{
SetVertex(v++, x, ySize, z);
}
}
//賦予下面頂點
for (int z = 1; z < zSize; z++)
{
for (int x = 1; x < xSize; x++)
{
SetVertex(v++, x, 0, z);
}
}
mesh.vertices = vertices;
mesh.normals = normals;
mesh.colors32 = CubeUV;
}
/// <summary>
/// 計算頂點 法線
/// </summary>
private void SetVertex(int i, int x , int y, int z)
{
Vector3 inner = vertices[i] = new Vector3(x, y, z);
if (x <Roundness)
{
inner.x = Roundness;
}
else if (x > xSize -Roundness)
{
inner.x = xSize - Roundness;
}
if (y < Roundness)
{
inner.y = Roundness;
}
else if (y> ySize -Roundness)
{
inner.y = ySize - Roundness;
}
if (z < Roundness)
{
inner.z = Roundness;
}
else if (z > zSize - Roundness)
{
inner.z = zSize - Roundness;
}
normals[i] = (vertices[i] - inner).normalized;
vertices[i] = inner + normals[i] * Roundness;
CubeUV[i] = new Color32((byte)x, (byte)y, (byte)z,0);
}
IEnumerator GenerateTriangles()
{
WaitForSeconds wait = new WaitForSeconds(0.1f);
int[] trianglesZ = new int[xSize * ySize * 12];
int[] trianglesX = new int[zSize*ySize*12];
int[] trianglesY = new int[xSize * zSize * 12];
int tZ = 0, tX = 0, tY = 0, v = 0;
int ring = (xSize + zSize) * 2;// 行與行的 頂點偏移量
for (int y = 0; y < ySize; y++, v++)
{
for (int q = 0; q < xSize; q++, v++)
{
tZ = SetQuad(trianglesZ, tZ, v, v+1, v+ring, v+ring+1);
}
for (int q = 0; q < zSize; q++, v++)
{
tX = SetQuad(trianglesX, tX, v, v + 1, v + ring, v + ring + 1);
}
for (int q = 0; q < xSize; q++, v++)
{
tZ = SetQuad(trianglesZ, tZ, v, v + 1, v + ring, v + ring + 1);
}
for (int q = 0; q < zSize-1; q++, v++)
{
tX = SetQuad(trianglesX, tX, v, v + 1, v + ring, v + ring + 1);
}
tX = SetQuad(trianglesX, tX, v, v -ring +1, v + ring, v + 1);
}
tY = CreateTopFace( trianglesY, tY, ring);
tY = CreateBottomFace(trianglesY, tY, ring);
mesh.subMeshCount = 3;
mesh.SetTriangles(trianglesZ, 0);
mesh.SetTriangles(trianglesX, 1);
mesh.SetTriangles(trianglesY, 2);
mesh.subMeshCount = 3;
mesh.SetTriangles(trianglesX, 0);
yield return wait;
}
/// <summary>
/// 建立上面
/// </summary>
/// <returns></returns>
int CreateTopFace( int [] trinagles, int t , int ring)
{
int v = ring * ySize;
for (int x = 0; x < xSize-1; x++,v++)
{
t = SetQuad( trinagles, t,v,v+1,v+ring-1,v+ring);
}
t = SetQuad( trinagles, t,v,v+1,v+ring-1,v+2);
int vMin = ring * (ySize + 1) - 1;
int vMid = vMin + 1;
int vMax = v + 2;
for (int z = 1; z < zSize-1; z++,vMin--,vMid++,vMax++)
{
t = SetQuad(trinagles, t, vMin, vMid, vMin - 1, vMid + xSize - 1);
for (int x = 1; x < xSize - 1; x++, vMid++)
{
t = SetQuad(trinagles, t, vMid, vMid + 1, vMid + xSize - 1, vMid + xSize);
}
t = SetQuad(trinagles, t, vMid, vMax, vMid + xSize - 1, vMax + 1);
}
//最後一行
int vTop = vMin - 2;
t = SetQuad(trinagles, t, vMin, vMid, vTop+1, vTop );
for (int x = 1; x < xSize-1; x++, vTop--,vMid++)
{
t = SetQuad(trinagles, t, vMid, vMid+1, vTop , vTop-1);
}
t = SetQuad(trinagles, t, vMid, vTop-2, vTop, vTop - 1);
return t;
}
/// <summary>
/// 建立底面
/// </summary>
/// <param name="trinagles"></param>
/// <param name="t"></param>
/// <param name="ring"></param>
/// <returns></returns>
int CreateBottomFace(int[] trinagles, int t, int ring)
{
int v = 1;
int vMid = vertices.Length - (xSize - 1) * (zSize - 1);
int vOriginMid = vMid;
t = SetQuad(trinagles, t, ring-1, vMid, 0, 1);
for (int x = 1; x < xSize-1; x++, vMid++,v++)
{
t = SetQuad(trinagles, t, vMid, vMid+1, v, v+1);
}
t = SetQuad(trinagles, t, vMid, v+2, v, v + 1);
/
int vMin = ring - 2;
int vMax = v + 2;
vMid++;
for (int z = 1; z < zSize-1; z++,vMin--,vMax++,vMid++,vOriginMid++)
{
t = SetQuad(trinagles, t, vMin, vMid, vMin + 1, vOriginMid);
for (int x = 1; x < xSize - 1; x++, vMid++, vOriginMid++)
{
t = SetQuad(trinagles, t, vMid, vMid + 1, vOriginMid, vOriginMid + 1);
}
t = SetQuad(trinagles, t, vMid, vMax + 1, vOriginMid, vMax);
}
int vTop = vMin - 1;
t = SetQuad(trinagles, t, vTop+1, vTop, vTop+2, vOriginMid);
for (int x = 1; x < xSize-1; x++, vOriginMid++,vTop--)
{
t = SetQuad(trinagles, t, vTop, vTop-1, vOriginMid, vOriginMid+1);
}
t = SetQuad(trinagles, t, vTop, vTop - 1, vOriginMid, vTop-2);
return t;
}
/// <summary>
/// 我們封裝這個 三角形拼接四邊形的方法 返回三角形的下一輪第一個索引 引數v00 是頂點的索引
/// </summary>
private static int SetQuad(int[] triangles, int i , int v00 , int v10 ,int v01 , int v11 )
{
triangles[i] = v00;
triangles[i + 2] = triangles[i + 3] = v10;
triangles[i + 1] = triangles[i + 4] = v01;
triangles[i + 5] = v11;
return i + 6;
}
private void OnDrawGizmos()
{
//if (vertices == null) return;
//for (int i = 0; i < vertices.Length; i++)
//{
// Gizmos.color = Color.black;
// Gizmos.DrawSphere( vertices[i] ,0.1f);
// Gizmos.color = Color.yellow;
// Gizmos.DrawRay(vertices[i],normals[i]);
//}
}
}
相關文章
- UE | Procedural Mesh 程式化網格體
- 服務網格 Service Mesh
- unity替換mesh測試Unity
- Unity Text Mesh 穿透問題Unity穿透
- 服務網格service mesh 之 Linkerd
- 網路程式設計(中)程式設計
- 服務網格新成員:亞馬遜釋出App Mesh應用網格亞馬遜APP
- java中須遵守的程式設計風格Java程式設計
- Unity3D中的C#程式設計初級Unity3DC#程式設計
- Emoji.voto,Linkerd 服務網格(service mesh)的示例應用程式
- 藍芽Mesh解決方案加速物聯網設計藍芽
- 為什麼要使用服務網格Service Mesh?
- 糟糕程式設計師的程式設計風格程式設計師
- 雲設計模式和Service Mesh設計模式
- Javascript程式設計風格JavaScript程式設計
- 為什麼我們需要服務網格Service mesh?
- Unity載入模組深度解析(網格篇)Unity
- 優秀Java程式設計師的程式設計風格Java程式設計師
- JavaScript 程式設計風格指南JavaScript程式設計
- 部落格連結—程式設計程式設計
- mesh組網
- 資料編織 (Data Fabric) vs 資料網格 (Data Mesh)
- 快速上手 Linkerd v2 Service Mesh(服務網格)
- Python程式設計風格和設計模式Python程式設計設計模式
- 網路程式設計中TCP與UDP程式設計TCPUDP
- 物件導向程式設計風格 VS 基於物件程式設計風格(boost::bind/function)物件程式設計Function
- Unity網格合併_材質合併[轉]Unity
- 程式設計師高逼格指南程式設計師
- Google Java 程式設計風格指南GoJava程式設計
- muduo網路庫學習筆記(0):物件導向程式設計風格和基於物件程式設計風格的比較筆記物件程式設計
- 網格上的網格計算
- 【go網路程式設計】-HTTP程式設計Go程式設計HTTP
- 服務網格將更安全:VMware收購Mesh7改變服務網格的遊戲規則遊戲
- Java 網路程式設計(TCP程式設計 和 UDP程式設計)Java程式設計TCPUDP
- k8s-服務網格實戰-配置 Mesh(灰度釋出)K8S
- 各種流行的程式設計風格程式設計
- Google Python 程式設計風格指南GoPython程式設計
- 前端 JavaScript 程式設計風格淺析前端JavaScript程式設計