前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >阅读笔记|创建无缝Mesh的立方体与圆形边缘的立方体

阅读笔记|创建无缝Mesh的立方体与圆形边缘的立方体

作者头像
keyle
发布2024-11-01 12:20:54
发布2024-11-01 12:20:54
7600
代码可运行
举报
文章被收录于专栏:礼拜八不工作礼拜八不工作
运行总次数:0
代码可运行

上一章讲到Mesh的工作原理以及顶点与三角形的算法.本章主题如下:

  • Create a cube with a seamless mesh. 创建无缝Mesh的立方体
  • Add rounded edges to the cube. 添加圆形边缘的立方体

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

https://catlikecoding.com/unity/tutorials/

Compositing a Cube 组合(方式)一个立方体

非重点,这里直接写实现思路.接上一章节生产面,只需修改每个面的角度位置.使其拼凑成为一个立方体即可.

使用六个面拼凑一个立方体

Creating Cube Vertices 创建立方体的顶点

计算所需定点数量

之前计算单个面的时候使用 (#x + 1)(#y + 1) 如下算法,那么可计算6个面的时候是不是可以直接套用单面的计算方式:2((#x + 1)(#y + 1) + (#x + 1)(#z + 1) + (#y + 1)(#z + 1)) 结论是否定的,其中角顶点与边顶点都被重复计算了。

顶点被重复计算次数的用颜色区分

这其实也不是什么大问题。事实上顶点重复是非常常见的,譬如我们通常用网格创建锐角。所以我们可以创建6个面(的顶点)合并到单个数组里。 但是这不是我们打算做的,因为我们已经知道如何创建网格。我们的cube不需要有重复的顶点,这种做法很有趣。 我们需要多少顶点呢?让我们按类型分解,首先8个角顶点,这很简单。有12条边,每四条在同向。因为我们不包括角,每个边都有一个等于相应大小的顶点减去一个顶点。或者,把它看作四组x、y和z边。

4(#x + #y + #z - 3)

其余的顶点是那些位于面部边缘的顶点。这是相当于一个重复的顶点,其体积缩小了2

2((#x - 1)(#y - 1) + (#x - 1)(#z - 1) + (#y - 1)(#z - 1))

这样计算出的结果就是最终所需顶点数

代码语言:javascript
代码运行次数:0
复制
private IEnumerator Generate () {
    GetComponent<MeshFilter>().mesh = mesh = new Mesh();
    mesh.name = "Procedural Cube";
    WaitForSeconds wait = new WaitForSeconds(0.05f);

    int cornerVertices = 8;
    int edgeVertices = (xSize + ySize + zSize - 3) * 4;
    int faceVertices = (
      (xSize - 1) * (ySize - 1) +
      (xSize - 1) * (zSize - 1) +
      (ySize - 1) * (zSize - 1)) * 2;
    vertices = new Vector3[cornerVertices + edgeVertices + faceVertices];

    yield return wait;
  }

现在定位一个面上的第一行顶点就像定位网格上的第一行顶点。(参考章节.1) 基础的算法是从x(0,0)开始,计算算一圈的点

代码语言:javascript
代码运行次数:0
复制
int v = 0; //索引
//算出X轴线的点
for (int x = 0; x <= xSize; x++)
{
    Vertices[v++] = new Vector3(x, 0, 0);
    yield return wait;
}
//算出y轴线的点
for (int z = 1; z <= zSize; z++)
{
    Vertices[v++] = new Vector3(xSize, 0, z);
    yield return wait;
}
//x轴线背后的点
for (int x = (int)xSize - 1; x >= 0; x--)
{
    Vertices[v++] = new Vector3(x, 0, zSize);
    yield return wait;
}
//z轴线背后的点
for (int z = (int)zSize - 1; z > 0; z--)
{
    Vertices[v++] = new Vector3(0, 0, z);
    yield return wait;
}

由以上基础我们可以直接绘制出第0层至顶层的点

代码语言:javascript
代码运行次数:0
复制
int v = 0;
for (int y = 0; y <= ySize; y++)
{
    //算出X轴线的点
    for (int x = 0; x <= xSize; x++)
    {
        Vertices[v++] = new Vector3(x, y, 0);
        yield return wait;
    }
    //算出y轴线的点
    for (int z = 1; z <= zSize; z++)
    {
        Vertices[v++] = new Vector3(xSize, y, z);
        yield return wait;
    }
    //x轴线背后的点
    for (int x = (int)xSize - 1; x >= 0; x--)
    {
        Vertices[v++] = new Vector3(x, y, zSize);
        yield return wait;
    }
    //z轴线背后的点
    for (int z = (int)zSize - 1; z > 0; z--)
    {
        Vertices[v++] = new Vector3(0, y, z);
        yield return wait;
    }
}

//顶层内部的点
for (int z = 1; z < zSize; z++)
{
    for (int x = 1; x < xSize; x++)
    {
        Vertices[v++] = new Vector3(x, ySize, z);
        yield return wait;
    }
}
//底层内部的点
for (int z = 1; z < zSize; z++)
{
    for (int x = 1; x < xSize; x++)
    {
        Vertices[v++] = new Vector3(x, 0, z);
        yield return wait;
    }
}

Add rounded edges to the cube. 添加圆形边缘的立方体

和上一章类似,我们这样绘制四边形

代码语言:javascript
代码运行次数:0
复制
private static int
SetQuad (int[] triangles, int i, int v00, int v10, int v01, int v11) {
    triangles[i] = v00;
    triangles[i + 1] = triangles[i + 4] = v01;
    triangles[i + 2] = triangles[i + 3] = v10;
    triangles[i + 5] = v11;
    return i + 6;
}

四边形图解

与顶点不同,三角形的数目等于六个面的总和。他们是否使用共享顶点并不重要。

代码语言:javascript
代码运行次数:0
复制
private void CreateTriangles () {
    int quads = (int)(xSize * ySize + xSize * zSize + ySize * zSize) * 2;
    int[] triangles = new int[quads * 6];
    mesh.triangles = triangles;
}

创建横向的三角方式与创建网格的做法相同。至此为止位置不同的是顶点在下一行的偏移相当全部的环形顶点之和。

代码语言:javascript
代码运行次数:0
复制
private void CreateTriangles () {
    int quads = (xSize * ySize + xSize * zSize + ySize * zSize) * 2;
    int[] triangles = new int[quads * 6];
    int ring = (xSize + zSize) * 2; //计算环偏移
    int t = 0, v = 0;

    for (int y = 0; y < ySize; y++, v++) {
        for (int q = 0; q < ring - 1; q++, v++) {
            t = SetQuad(triangles, t, v, v + 1, v + ring, v + ring + 1);
        }
        t = SetQuad(triangles, t, v, v - ring + 1, v + ring, v + 1);
    }

    t = CreateTopFace(triangles, t, ring);
    t = CreateBottomFace(triangles, t, ring);
    mesh.triangles = triangles;
}

很不幸顶部与底部的面并不简单。顶点的布局就像是一个网格被环包围。

盖子就像在环里的网格

代码语言:javascript
代码运行次数:0
复制
private int CreateTopFace (int[] triangles, int t, int ring) {
    int v = ring * ySize;
    for (int x = 0; x < xSize - 1; x++, v++) {
        t = SetQuad(triangles, t, v, v + 1, v + ring - 1, v + ring);
    }
    t = SetQuad(triangles, 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(triangles, t, vMin, vMid, vMin - 1, vMid + xSize - 1);
        for (int x = 1; x < xSize - 1; x++, vMid++) {
            t = SetQuad(
                triangles, t,
                vMid, vMid + 1, vMid + xSize - 1, vMid + xSize);
        }
        t = SetQuad(triangles, t, vMid, vMax, vMid + xSize - 1, vMax + 1);
    }

    int vTop = vMin - 2;
    t = SetQuad(triangles, t, vMin, vMid, vTop + 1, vTop);
    for (int x = 1; x < xSize - 1; x++, vTop--, vMid++) {
        t = SetQuad(triangles, t, vMid, vMid + 1, vTop, vTop - 1);
    }
    t = SetQuad(triangles, t, vMid, vTop - 2, vTop, vTop - 1);

    return t;
}

private int CreateBottomFace (int[] triangles, int t, int ring) {
    int v = 1;
    int vMid = vertices.Length - (xSize - 1) * (zSize - 1);
    t = SetQuad(triangles, t, ring - 1, vMid, 0, 1);
    for (int x = 1; x < xSize - 1; x++, v++, vMid++) {
        t = SetQuad(triangles, t, vMid, vMid + 1, v, v + 1);
    }
    t = SetQuad(triangles, t, vMid, v + 2, v, v + 1);

    int vMin = ring - 2;
    vMid -= xSize - 2;
    int vMax = v + 2;

    for (int z = 1; z < zSize - 1; z++, vMin--, vMid++, vMax++) {
        t = SetQuad(triangles, t, vMin, vMid + xSize - 1, vMin + 1, vMid);
        for (int x = 1; x < xSize - 1; x++, vMid++) {
            t = SetQuad(
                triangles, t,
                vMid + xSize - 1, vMid + xSize, vMid, vMid + 1);
        }
        t = SetQuad(triangles, t, vMid + xSize - 1, vMax + 1, vMid, vMax);
    }

    int vTop = vMin - 1;
    t = SetQuad(triangles, t, vTop + 1, vTop, vTop + 2, vMid);
    for (int x = 1; x < xSize - 1; x++, vTop--, vMid++) {
        t = SetQuad(triangles, t, vTop, vTop - 1, vMid, vMid + 1);
    }
    t = SetQuad(triangles, t, vTop, vTop - 1, vMid, vTop - 2);

    return t;
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 礼拜八不工作 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Compositing a Cube 组合(方式)一个立方体
  • Creating Cube Vertices 创建立方体的顶点
    • 计算所需定点数量
  • Add rounded edges to the cube. 添加圆形边缘的立方体
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档