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 Text Mesh 穿透問題Unity穿透
- 服務網格service mesh 之 Linkerd
- Unity3D中的C#程式設計初級Unity3DC#程式設計
- Emoji.voto,Linkerd 服務網格(service mesh)的示例應用程式
- 雲設計模式和Service Mesh設計模式
- 為什麼要使用服務網格Service Mesh?
- 服務網格新成員:亞馬遜釋出App Mesh應用網格亞馬遜APP
- 網路程式設計中TCP與UDP程式設計TCPUDP
- 為什麼我們需要服務網格Service mesh?
- 快速上手 Linkerd v2 Service Mesh(服務網格)
- 【go網路程式設計】-HTTP程式設計Go程式設計HTTP
- Java 網路程式設計(TCP程式設計 和 UDP程式設計)Java程式設計TCPUDP
- mesh組網
- .NET程式設計5月小結 - Blazor, Unity, Dependency Injection程式設計BlazorUnity
- 【Linux網路程式設計】網路程式設計常見概念Linux程式設計
- 資料編織 (Data Fabric) vs 資料網格 (Data Mesh)
- 程式設計和網路程式設計入門程式設計
- JAVA網路程式設計(2)TCP程式設計Java程式設計TCP
- 網路程式設計程式設計
- Python網路程式設計——程式Python程式設計
- java程式設計規約----程式碼風格(一)Java程式設計
- Java中神經網路Triton GPU程式設計Java神經網路GPU程式設計
- linux網路程式設計中的errno處理Linux程式設計
- Java 網路程式設計 —— 非阻塞式程式設計Java程式設計
- 【網路程式設計】阻塞IO程式設計的坑程式設計
- 各種流行的程式設計風格程式設計
- 玩轉 PHP 網路程式設計全套之多程式程式設計PHP程式設計
- Mesh模型的Laplace Deformation(網格形變 - 拉普拉斯形變) - C++程式碼實現模型ORMC++
- Golang 網路程式設計Golang程式設計
- 網路程式設計概述程式設計
- Java 網路程式設計Java程式設計
- socket網路程式設計程式設計
- JAVA網路程式設計Java程式設計
- 網路程式設計-socket程式設計
- 網路程式設計-UDP程式設計UDP
- k8s-服務網格實戰-配置 Mesh(灰度釋出)K8S