这篇我来讲一下rectangle长方形拓扑网格的创建,大部分时候,3d图形引擎提供的基础立体网格并不能完全达到我们学习的要求,就比如unity,我需要一个拓扑信息完好的rectangle长方形就没法提供了,此时我们只能使用图形api来代码创建一个。
首先我来解释一下mesh所包含的信息,也就是Vertices,Triangles,以及uvs,什么意思呢?看下图:
上图中正方形假设是我们要创建的mesh网格,那么我们创建这个网格,首先要知道四个顶点的坐标,也就是vertices,其次我们还要知道拓扑信息,也就是节点(或者说坐标点)之间的关联信息,比如图形学中网格三角面的三个顶点的逆时针顺时针拓扑信息,这个正方形网格包含两个三角面,那么三角面的拓扑信息就是(012),(023),这就是triangles。最后如果这个网格要承载一张贴图,那么贴图的每个顶点对应的网格的顶点是怎么样的呢?这个也就是uvs所记录的信息。
所以说一个网格需要包含着三种信息才能在图形程序中使用。那么unity要创建一个这种正方形具体怎么办呢?代码如下:
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
-
public class MeshSquare : MonoBehaviour
-
{
-
private Mesh mMesh;
-
-
void Start()
-
{
-
mMesh = new Mesh();
-
Vector3[] vertices = new Vector3[4] {
-
new Vector3(0,0,0),
-
new Vector3(1,0,0),
-
new Vector3(1,0,1),
-
new Vector3(0,0,1)
-
};
-
int[] triangles = new int[6] {
-
0,1,2,
-
0,2,3
-
};
-
Vector2[] uvs = new Vector2[4]
-
{
-
new Vector3(0, 0),
-
new Vector3(1, 0),
-
new Vector3(0, 1),
-
new Vector3(1, 1),
-
};
-
mMesh.vertices = vertices;
-
mMesh.triangles = triangles;
-
mMesh.uv = uvs;
-
GetComponent<MeshFilter>().sharedMesh = mMesh;
-
}
-
-
}
可以看得出代码就是上面讲的正方形创建方法,效果就是这样的:
绑定meshfilter和meshrenderer以及材质球后就能得到一个正方形了。
可惜啊可惜,实际上我们写图形程序中需要的大部分时候都是长方形,而不是这么规范的正方形,比如这个矩阵论书籍的封面就是600*820分辨率的,那么其实我们只需要修改vertices中的网格点坐标就达到目的了,比如这样:
改下顶点坐标就达到目的了。实际上这种方式在我们图形学计算中会导致很多问题,因为这种网格不是单位化的,也就是说网格的长宽比例不同,如果我们要是想用无数个单位正方形组成长方形该怎么办呢?下面我描绘一下长方形的拓扑信息,如下图:
这里我没有标明坐标和uv信息,因为坐标和uv只需要通过坐标系的xy进行for循环计算就得到了,可以根据需要任意轴向的正负计算,所以这里我只标明了长方形网格的拓扑三角信息,比如这时候就是(0,4,5),(0,5,1),(1,5,6),(1,6,2)...,这时候我们就来写程序吧,如下图:
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
-
[ExecuteInEditMode]
-
public class MeshRectangle : MonoBehaviour {
-
-
public bool Refresh = false;
-
[SerializeField]public int xCount = 60; //单位方块x轴数量
-
[SerializeField]public int yCount = 82; //单位方块y轴数量
-
-
private float mCellLen = 0.1f; //单位小方块边长
-
-
private Mesh mMesh;
-
-
void Start()
-
{
-
CreateMesh();
-
}
-
-
void Update()
-
{
-
if (Refresh)
-
{
-
CreateMesh();
-
Refresh = false;
-
}
-
}
-
-
private void CreateMesh()
-
{
-
//构建一个任意单位长宽的长方形
-
mMesh = new Mesh();
-
int xPointCount = xCount + 1; //x轴网格点数量
-
int yPointCount = yCount + 1; //y轴网格点数量
-
int xyMeshPointCount = xPointCount * yPointCount; //网格顶点的数量
-
int triangleCount = xCount * yCount * 2; //三角面数量(小正方形的两倍)
-
//构建mesh网格的所有信息数组
-
Vector3[] vertices = new Vector3[xyMeshPointCount];
-
int[] triangles = new int[triangleCount * 3];
-
Vector2[] uvs = new Vector2[xyMeshPointCount];
-
//记录拓扑信息循环的间隔
-
int triangleIndex = 0;
-
for (int x = 0; x < xPointCount; x++)
-
{
-
for (int y = 0; y < yPointCount; y++)
-
{
-
int index = x + y * xPointCount;
-
vertices[index] = new Vector3((xCount - x) * mCellLen, 0, (yCount - y) * mCellLen);
-
-
if (x < xCount && y < yCount)
-
{
-
//这里就是拓扑信息的循环计算,结合绘画的拓扑信息图算一下
-
triangles[triangleIndex] = x + y * xPointCount;
-
triangles[triangleIndex + 1] = x + (y + 1) * xPointCount;
-
triangles[triangleIndex + 2] = x + (y + 1) * xPointCount + 1;
-
-
triangles[triangleIndex + 3] = x + y * xPointCount;
-
triangles[triangleIndex + 4] = x + (y + 1) * xPointCount + 1;
-
triangles[triangleIndex + 5] = x + y * xPointCount + 1;
-
-
triangleIndex += 6;
-
}
-
uvs[index] = new Vector2((float)x / (float)xCount, (float)y / (float)yCount);
-
}
-
}
-
-
mMesh.vertices = vertices;
-
mMesh.triangles = triangles;
-
mMesh.uv = uvs;
-
GetComponent<MeshFilter>().sharedMesh = mMesh;
-
}
-
-
}
看下实际运行效果,如下图:
我们按照60:82的宽高比来绘制网格,这样矩阵论的封面网格就匹配了,顺便看下我们生成的网格,如下图:
生成的网格数量和三角面以及uv都是符合我们需求的。这种网格生成方式我们以后会用来制作计算机图形程序,如果没有这种需求,那么就按照我最开始生成四个顶点的网格方式生成节省资源会更好。