(大部分内容是我自己的理解,如果出现了错误地方望不吝赐教)
我们可以通过控制unity世界中的顶点来生成mesh网格
由于Unity的渲染方式是单向渲染, 我们需要控制每个三角面的法线方向
根据左手定则,我们可以根据法线方向来确定我们顶点的顺序
但是如果只用一个Vector3数组来存储所有三角形的位置信息,会导致大量空间的浪费,所以我们使用类似于OpenGL中的
VAO概念,给所有顶点的逻辑顺序进行编号,然后我们根据对应的index在顶点数组中寻找对应的元素,然后再将这三个点连接成一个三角面
我们根据物体本地坐标系,给cube的六个面,分别标记为front,back,up,down,left,right
以front为例
三角面的构造顺序为(0, 3, 2)和(0, 2, 1)
以此类推可以得到以下代码:
void GenerateCube()
{
mesh.vertices = new Vector3[]
{
new Vector3(0,0,0),
new Vector3(1,0,0),
new Vector3(1,1,0),
new Vector3(0,1,0),
new Vector3(0,1,1),
new Vector3(1,1,1),
new Vector3(1,0,1),
new Vector3(0,0,1)
};
mesh.triangles = new int[]
{
0, 3, 2,//前
0, 2, 1,
7, 4, 3,//左
7, 3, 0,
6, 5, 4,//后
6, 4, 7,
1, 2, 5,//右
1, 5, 6,
2, 3, 4,//上
2, 4, 5,
1, 7, 0,//下
1, 6, 7
};
}
画完正方体,我们给他手动添加一个shader,这个时候会发现,这个立方体的光照会出现问题,为什么会发生这种问题?
在unity的光照计算中,我们实际上使用顶点法线normal计算光照,但是我们在构成正方体的时候,顶点信息是复用的,由于unity只允许一个顶点对应一个法线,法线会出现覆盖的情况,这样在计算的时候某个点在某个面的法线信息就会丢失,为了正确得到光照,我们需要把所有面分开。
使用Mesh控制生成圆
我们需要使用一个segments变量来控制分割的块数
同时顶点的数目是需要在其基础上加1
//顶点数组大小
int verticesCount = segments + 1;
Vector3[] vertices = new Vector3[verticesCount];
vertices[0] = Vector3.zero;//首元素为圆的中心
为了计算每次分割的步长,我们需要定义一个变量currAngle来记录当前的角度
//计算每个分割的度数(弧度)
float angleDegree = 360.0f;
float angleRad = Mathf.Deg2Rad * angleDegree;
float currAngle = angleRad;//从最大角度开始
float detlaAngle = angleRad / segments;//计算角度变化
在计算的时候,我们需要注意一个问题,我们生成三角顶点顺序的时候是按照顺时针(0,1,2)(0,2,3)(0,3,4)...(0,n-1,n)(0,n,1)最后一个三角形需要拿出单独处理才能把圆形拼接上
for (int i = 1; i < verticesCount; i++)
{
float cosTheta = Mathf.Cos(currAngle);
float sinTheta = Mathf.Sin(currAngle);
vertices[i] = new Vector3(cosTheta * radius,0, sinTheta * radius);
currAngle -= detlaAngle;
}
//构造三角形
int triangleCount = segments * 3;
int[] triangles = new int[triangleCount];
//这里没有全部处理,
for (int i = 0, vertexIndex = 1; i < triangleCount; i += 3, vertexIndex++)//每次处理三个顶点
{
triangles[i] = 0;
triangles[i + 1] = vertexIndex;
triangles[i + 2] = vertexIndex + 1;
}
//最后一个三角形单独处理
triangles[triangleCount - 3] = 0;
triangles[triangleCount - 2] = verticesCount - 1;
triangles[triangleCount - 1] = 1;