Unity-网格编程
1. 简介
1. 基础理论
- 模型是由点和面构成的,每三个点构成一个三角面。
- 根据三个顶点排列的顺序,根据左手定则决定三角面的正反面
- 三角形序列是一组int数组,数组元素数量为3的倍数,表示三角形的顶点 对应的顶点ID
- Unity想要显示一个模型,必须在对象上挂载组件Mesh Filter(网格过滤器)与Mesh Renderer(网格渲染器)
2. Mesh构成
- Vertex
- Normal
- UV
- Trangle(三角形序列)
2. 基本函数
1. 使用代码创建Mesh模型
1. Mesh类
- Unity允许使用Mesh类创建模型,并将创建的Mesh赋值给MeshFilter。
- 模型顶点列表 记录了所有顶点的位置信息;
三角形序列 决定了哪三个顶点会构成一个三角面。以左手定则决定面的正方向;
UV坐标列表 决定了每个顶点对应UV纹理坐标的具体位置。三角面之间的UV值将通过三个顶点的UV值,以插值的方式确定面每个位置的的UV值;
Mesh参数 | 描述 |
---|---|
name | 模型名称 |
vertices | 模型顶点列表 |
triangles | 三角形序列(序列数量必须为3的倍数) |
uv | UV坐标列表 |
normals | 法线列表 |
tangents | 切线列表 |
Mesh函数 | 描述 |
---|---|
RecalculateNormals() | 自动计算法线方向 |
RecalculateTangents() | 自动计算切线方向 |
RecalculateBounds() | 重新计算模型边缘界限 |
2. 示例
一个正方形
MeshFilter filter;
void Start()
{
filter = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mesh.name = "Mesh_01";
mesh.vertices = GetVertexs();
mesh.triangles = GetTriangles();
mesh.uv = GetUVs();
mesh.normals = GetNormals();
mesh.tangents = GetTangent();
filter.mesh = mesh;
}
// 设定顶点位置
Vector3[] GetVertexs()
{
return new Vector3[]
{
new Vector3(0, 0, 0),
new Vector3(1, 0, 0),
new Vector3(0, 1, 0),
new Vector3(1, 1, 0),
};
}
// 设定三角形序列
int[] GetTriangles()
{
return new int[]
{
0, 1, 2, 1, 3, 2
};
}
// 设定UV
Vector2[] GetUVs()
{
return new Vector2[]
{
new Vector2(1, 0),
new Vector2(0, 0),
new Vector2(1, 1),
new Vector2(0, 1),
};
}
// 设定顶点位置
Vector3[] GetNormals()
{
return new Vector3[]
{
new Vector3(0, 0, 1),
new Vector3(0, 0, 1),
new Vector3(0, 0, 1),
new Vector3(0, 0, 1),
};
}
// 设定顶点位置
Vector4[] GetTangent()
{
return new Vector4[]
{
new Vector4(-1, 0, 0, -1),
new Vector4(-1, 0, 0, -1),
new Vector4(-1, 0, 0, -1),
new Vector4(-1, 0, 0, -1),
};
}
动态创建指定尺寸的矩形
public int width, height;
MeshFilter filter;
private void OnDrawGizmos()
{
Start();
}
void Start()
{
filter = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
DrawMesh(mesh);
filter.mesh = mesh;
}
void DrawMesh(Mesh mesh)
{
mesh.name = "Mesh_02";
width = width > 0 ? width : 0;
height = height > 0 ? height : 0;
// 顶点列表
Vector3[] vertices = new Vector3[(width 1) * (height 1)];
Vector2[] uvs = new Vector2[(width 1) * (height 1)];
int[] triangles = new int[width * height * 2 * 3];
for (int y = 0; y < height 1; y )
{
for (int x = 0; x < width 1; x )
{
vertices[x y * (width 1)] = new Vector3(x, y, 0);
uvs[x y * (width 1)] = new Vector2((float)x / width, (float)y / height);
}
}
// 开始坐标依次递增,内层循环在最后额外让开始坐标 1.从而避开了结尾点
for (int y = 0, trianglesIndex = 0, startIndex = 0; y < height; y , startIndex )
{
for (int x = 0; x < width; x , startIndex , trianglesIndex = 6)
{
triangles[trianglesIndex] = startIndex width 1;
triangles[trianglesIndex 1] = startIndex 1;
triangles[trianglesIndex 2] = startIndex;
triangles[trianglesIndex 3] = startIndex width 1;
triangles[trianglesIndex 4] = startIndex width 2;
triangles[trianglesIndex 5] = startIndex 1;
}
}
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
}
创建正方体
void DrawMesh(Mesh mesh)
{
mesh.name = "Mesh_03";
Vector3[] vertices = new Vector3[8]
{
new Vector3(-0.5f, -0.5f, -0.5f),
new Vector3(0.5f, -0.5f, -0.5f),
new Vector3(-0.5f, 0.5f, -0.5f),
new Vector3(0.5f, 0.5f, -0.5f),
new Vector3(-0.5f, -0.5f, 0.5f),
new Vector3(0.5f, -0.5f, 0.5f),
new Vector3(-0.5f, 0.5f, 0.5f),
new Vector3(0.5f, 0.5f, 0.5f),
};
int[] triangles = new int[]
{
0, 3, 1,
0, 2, 3,
2, 6, 7,
2, 7, 3,
3, 7, 5,
3, 5, 1,
0, 4, 6,
0, 6, 2,
1, 5, 4,
1, 4, 0,
6, 4, 5,
6, 5, 7
};
foreach (var vertex in vertices) Gizmos.DrawSphere(vertex transform.position, 0.15f);
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
mesh.RecalculateTangents();
mesh.RecalculateBounds();
}
创建圆角正方体,胶囊体,球体
public int XGridCount, YGridCount, ZGridCount;
public float XSize, YSize, ZSize, Radius;
public bool debug;
MeshFilter filter;
/// <summary>
/// 顶点数量
/// </summary>
int VertexCount
{
get
{
// 顶角顶点数量
int connerVertexCount = 8;
// 边顶点数量
int edgeVertexCount = (XGridCount YGridCount ZGridCount - 3) * 4;
// 面顶点数量
int faceVertexCount = (XGridCount - 1) * (YGridCount - 1) * 2 (XGridCount - 1) * (ZGridCount - 1) * 2 (ZGridCount - 1) * (YGridCount - 1) * 2;
return connerVertexCount edgeVertexCount faceVertexCount;
}
}
/// <summary>
/// 三角形序列数量
/// </summary>
int TriangeCount
{
get
{
return XGridCount * YGridCount * 4 XGridCount * ZGridCount * 4 ZGridCount * YGridCount * 4;
}
}
int FloorCount
{
get
{
return (XGridCount ZGridCount) * 2;
}
}
private void OnDrawGizmos()
{
Start();
}
void Start()
{
filter = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
DrawMesh(mesh);
filter.mesh = mesh;
}
void DrawMesh(Mesh mesh)
{
mesh.name = "Mesh_04";
XGridCount = XGridCount >= 1 ? XGridCount : 1;
YGridCount = YGridCount >= 1 ? YGridCount : 1;
ZGridCount = ZGridCount >= 1 ? ZGridCount : 1;
XSize = XSize >= 1 ? XSize : 1;
YSize = YSize >= 1 ? YSize : 1;
ZSize = ZSize >= 1 ? ZSize : 1;
Radius = Radius < XSize / 2 ? Radius : XSize / 2;
Radius = Radius < YSize / 2 ? Radius : YSize / 2;
Radius = Radius < ZSize / 2 ? Radius : ZSize / 2;
SetVertex(mesh);
SetNormal(mesh);
SetTriange(mesh);
}
void SetVertex(Mesh mesh)
{
Vector3[] vertices = new Vector3[VertexCount];
int index = 0;
for (int y = 0; y < YGridCount 1; y )
{
for (int i = 0; i < XGridCount; i , index )
{
vertices[index] = new Vector3((float)i / XGridCount * XSize, (float)y / YGridCount * YSize, 0);
}
for (int i = 0; i < ZGridCount; i , index )
{
vertices[index] = new Vector3(XSize, (float)y / YGridCount * YSize, (float)i / ZGridCount * ZSize);
}
for (int i = XGridCount; i > 0; i--, index )
{
vertices[index] = new Vector3((float)i / XGridCount * XSize, (float)y / YGridCount * YSize, ZSize);
}
for (int i = ZGridCount; i > 0; i--, index )
{
vertices[index] = new Vector3(0, (float)y / YGridCount * YSize, (float)i / ZGridCount * ZSize);
}
}
for (int z = 1; z < ZGridCount; z )
{
for (int x = 1; x < XGridCount; x , index )
{
vertices[index] = new Vector3((float)x / XGridCount * XSize, ZSize, (float)z / ZGridCount * ZSize);
}
}
for (int z = 1; z < ZGridCount; z )
{
for (int x = 1; x < XGridCount; x , index )
{
vertices[index] = new Vector3((float)x / XGridCount * XSize, 0, (float)z / ZGridCount * ZSize);
}
}
mesh.vertices = vertices;
}
void SetTriange(Mesh mesh)
{
int[] triangles = new int[TriangeCount * 3];
int index = 0;
// 生成边缘一圈
for (int h = 0; h < YGridCount; h )
{
for (int i = 0; i < FloorCount - 1; i , index )
{
SetQuad(triangles, index * 6, index, index 1, index FloorCount, index FloorCount 1);
}
SetQuad(triangles, index * 6, index, h * FloorCount, index FloorCount, (h 1) * FloorCount);
}
// 生成顶面左下边
for (int x = 0; x < XGridCount - 1; x , index )
{
SetQuad(triangles, index * 6, index, index 1, index FloorCount - 1, index FloorCount);
}
// 生成顶面右下角
SetQuad(triangles, index * 6, index, index 1, index FloorCount - 1, index 2);
// 第二行第一个面的v00
int topMin = FloorCount * (YGridCount 1) - 1;
// 生成左右侧边
for (int i = 0; i < ZGridCount - 2; i , index )
{
SetQuad(triangles, index * 6, topMin - i, topMin 1 i * (XGridCount - 1), topMin - 1 - i, topMin 1 (i 1) * (XGridCount - 1));
}
for (int i = 0; i < ZGridCount - 2; i , index )
{
SetQuad(triangles, index * 6, topMin (XGridCount - 1) * (i 1), topMin - FloorCount XGridCount 2 i, topMin (XGridCount - 1) * (i 2), topMin - FloorCount XGridCount 3 i);
}
for (int z = 0; z < ZGridCount - 2; z )
{
for (int x = 0; x < XGridCount - 2; x , index )
{
SetQuad(triangles, index * 6,
topMin x z * (XGridCount - 1) 1,
topMin x z * (XGridCount - 1) 2,
topMin x z * (XGridCount - 1) XGridCount,
topMin x z * (XGridCount - 1) XGridCount 1);
}
}
SetQuad(triangles, index * 6, topMin - ZGridCount 2, topMin (XGridCount - 1) * (ZGridCount - 2) 1, topMin - ZGridCount 1, topMin - ZGridCount);
for (int i = 0; i < XGridCount - 2; i , index )
{
SetQuad(triangles, index * 6, topMin (XGridCount - 1) * (ZGridCount - 2) 1 i, topMin (XGridCount - 1) * (ZGridCount - 2) 2 i, topMin - ZGridCount - i, topMin - ZGridCount - 1 - i);
}
SetQuad(triangles, index * 6, topMin (XGridCount - 1) * (ZGridCount - 1), topMin - (ZGridCount - 1) - (XGridCount - 1) - 2, topMin - (ZGridCount - 1) - (XGridCount - 1), topMin - (ZGridCount - 1) - (XGridCount - 1) - 1);
// 地面中间第一个点
int btmMin = topMin (XGridCount - 1) * (ZGridCount - 1) 1;
SetQuad(triangles, index * 6, FloorCount - 1, btmMin, 0, 1);
for (int i = 0; i < XGridCount - 2; i , index )
{
SetQuad(triangles, index * 6, btmMin i, btmMin 1 i, 1 i, 2 i);
}
SetQuad(triangles, index * 6, btmMin XGridCount - 2, XGridCount 1, XGridCount - 1, XGridCount);
for (int i = 0; i < ZGridCount - 2; i , index )
{
SetQuad(triangles, index * 6, FloorCount - 2 - i, btmMin (XGridCount - 1) * (i 1), FloorCount - 1 - i, btmMin (XGridCount - 1) * i);
}
for (int i = 0; i < ZGridCount - 2; i , index )
{
SetQuad(triangles, index * 6, btmMin (XGridCount - 1) * (2 i) - 1, XGridCount 2 i, btmMin (XGridCount - 1) * (1 i) - 1, XGridCount 1 i);
}
for (int z = 0; z < ZGridCount - 2; z )
{
for (int x = 0; x < XGridCount - 2; x , index )
{
SetQuad(triangles, index * 6,
btmMin x (z 1) * (XGridCount - 1),
btmMin x (z 1) * (XGridCount - 1) 1,
btmMin x z * (XGridCount - 1),
btmMin x z * (XGridCount - 1) 1);
}
}
SetQuad(triangles, index * 6, FloorCount - ZGridCount, FloorCount - ZGridCount - 1, FloorCount - ZGridCount 1, btmMin (XGridCount - 1) * (ZGridCount - 2));
for (int i = 0; i < XGridCount - 2; i , index )
{
SetQuad(triangles, index * 6, FloorCount - ZGridCount - i - 1, FloorCount - ZGridCount - i - 2, btmMin (XGridCount - 1) * (ZGridCount - 2) i, btmMin (XGridCount - 1) * (ZGridCount - 2) i 1);
}
SetQuad(triangles, index * 6, ZGridCount XGridCount 1, ZGridCount XGridCount, btmMin (XGridCount - 1) * (ZGridCount - 1) - 1, ZGridCount XGridCount - 1);
mesh.triangles = triangles;
}
void SetNormal(Mesh mesh)
{
Vector3[] normals = new Vector3[VertexCount];
Vector3[] vertices = mesh.vertices;
for (int i = 0; i < vertices.Length; i )
{
SetNormalPoint(vertices, normals, i);
if (debug) Gizmos.DrawSphere(transform.position vertices[i], .07f);
}
mesh.normals = normals;
mesh.vertices = vertices;
}
/// <summary>
/// 构建圆角四边形
/// </summary>
void SetNormalPoint(Vector3[] vertices, Vector3[] normals, int i)
{
var vertex = vertices[i];
// 圆心
var inner = vertex;
if (vertex.x < Radius)
{
inner.x = Radius;
}
else if (vertex.x > XSize - Radius)
{
inner.x = XSize - Radius;
}
if (vertex.y < Radius)
{
inner.y = Radius;
}
else if (vertex.y > YSize - Radius)
{
inner.y = YSize - Radius;
}
if (vertex.z < Radius)
{
inner.z = Radius;
}
else if (vertex.z > ZSize - Radius)
{
inner.z = ZSize - Radius;
}
normals[i] = (vertex - inner).normalized;
vertices[i] = normals[i] * Radius inner;
}
/// <summary>
/// 设置面片
/// </summary>
void SetQuad(int[] triangles, int i, int v00, int v10, int v01, int v11)
{
triangles[i] = v00;
triangles[i 1] = v01;
triangles[i 2] = v11;
triangles[i 3] = v00;
triangles[i 4] = v11;
triangles[i 5] = v10;
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfhbhff
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01