接上回 Rounded Cube 1.本章主题如下:

  • Define normals. 定义法线

此为本人阅读笔记不作为转载处理,详细还请参看原文. 原文地址

Rounding the Cube 圆形方块

先设置一个roundness参数(数值),并且添加法线字段。

1
2
3
4
5
6
7
8
9
10
11
12
private Vector3[] normals;

private void CreateVertices () {

vertices = new Vector3[cornerVertices + edgeVertices + faceVertices];
normals = new Vector3[vertices.Length];



mesh.vertices = vertices;
mesh.normals = normals;
}

我们添加如下方法来计算对于每个顶点的法线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private void CreateVertices () {

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;
}

private void SetVertex (int i, int x, int y, int z) {
vertices[i] = new Vector3(x, y, z);
}

嗯。然后我们如何定位顶点呢?想象一下一个小一点的cube在原cube内部。这两cube之间的距离等于圆滑程度(值)。你可以想象圆粘在小立方体的角落上,它的半径就等于平滑值,所以内部的cube牢牢的抓住(外部的cube).

对于外部立方体上的任何点,在内部立方体中都有一个最靠近它的点.我们可以用这个来确定圆形cube的法线向量。

想象另外一个立方体在里面

圆形cube表面的点可以被起始于内部并且沿着法线方向移动的量等于圆滑值的点所达到。 –我的理解
圆形立方体的表面点可以从内点开始,沿着法线方向移动,其量等于圆度. – 百度翻译
The surface points of the rounded cube can then be found by starting at the inner point and moving along the normal by an amount equal to the roundness. – 原文

下面是参考代码,并未计算出内部的点

1
2
3
4
5
6
private void SetVertex (int i, int x, int y, int z) {
Vector3 inner = vertices[i] = new Vector3(x, y, z);

normals[i] = (vertices[i] - inner).normalized;
vertices[i] = inner + normals[i] * roundness;
}

现在找到内部的点,开始检查x轴的坐标。如果小于圆滑值就在内部cube的左侧并且在内部x坐标就是简单的圆滑值。如果我们超出了立方体的x大小减去圆滑值,那么我们就在右边。在所有其他情况下,我们在内cube,点共享相同的x坐标范围

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}

normals[i] = (vertices[i] - inner).normalized;
vertices[i] = inner + normals[i] * roundness;
}

一维四舍五入相当平滑

到目前为止,结果看起来并不圆润,但我们已经在正负X方向上获得了正常值。 对Y坐标进行同样的检查。

1
2
3
4
5
6
7
8
9
10
11
12
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;
}

在两个纬度上处理圆滑

现在看起来好点了! 圆角和法线在XY平面上工作。 剩下的就是检查Z坐标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
}

完全圆滑

我们终于有了一个完全圆润的立方体。