内容纲要

传送门

效果图

Partical System(传送门、图腾)插图

详细参数

Partical System(传送门、图腾)插图(1)

Partical System(传送门、图腾)插图(2)

Partical System(传送门、图腾)插图(3)

Partical System(传送门、图腾)插图(4)

Partical System(传送门、图腾)插图(5)

Partical System(传送门、图腾)插图(6)

Partical System(传送门、图腾)插图(7)

图腾

Mesh绘图的一点心得(与本次地面火焰图腾制作无关)

绘图的必要组件:

  • Mesh:是指模型的网格,建模就是建网格。细看Mesh,可以知道Mesh的主要属性内容包括顶点坐标,法线,纹理坐标,三角形绘制序列等其他有用属性和功能。因此建网格,就是画三角形;画三角形就是定位三个点。
  • Mesh Filter:内包含一个Mesh组件,可以根据MeshFilter获得模型网格的组件,也可以为MeshFilter设置Mesh内容。
  • Mesh Renderer:是用于把网格渲染出来的组件。MeshFilter的作用就是把Mesh扔给MeshRender将模型或者说是几何体绘制显示出来。

Mesh所绘制的图都是由三角形构成的,关键在于形成三角形的顶点坐标,以及这些顶点坐标的顺序。

关于用Mesh绘制圆柱体:
首先绘制圆形:
Partical System(传送门、图腾)插图(8)

// 6.28318f是2PI
// edg_x是边的数量
// reg是每条边对应的三角函数中的θ角(弧度制)
float reg = 6.28318f / edg_x;

// rad是圆心的半径
// (reg * (x % edg_x)) % 6.28318f是每个构成圆边的点所在的位置。
// 二维空间中的圆形画法公式
Vector2(Mathf.Cos((reg * (x % edg_x)) % 6.28318f) * rad, Mathf.Sin((reg * (x % edg_x)) % 6.28318f) * rad);

程序源码:

private void UpdateMesh(Mesh mesh, int edg_x, int edg_y, float rad, float len)
    {
        edg_x = Mathf.Max(2, edg_x);//保证最低2个边
        edg_y = Mathf.Max(2, edg_y);
        int _deglen = (edg_x + 1) * edg_y;//长方体
        int totalcount = _deglen + (1 + edg_x + 1) * 2; //加两个圆

        // 法线
        Vector3[] normals = new Vector3[totalcount];
        // 顶点
        Vector3[] verts = new Vector3[totalcount];
        //Vector2[] uvs = new Vector2[totalcount];
        // 顶点排序
        int[] trians = new int[edg_x * edg_y * 6];
        // 每条边所占用的角度
        float reg = 6.28318f / edg_x;
        float _len = len / (edg_y - 1);

        for (int y = 0; y < edg_y; y++)
            for (int x = 0; x < edg_x + 1; x++)//多一个边来保存UV值
            {
                int i = x + y * (edg_x + 1);
                verts[i] = new Vector3(Mathf.Sin((reg * (x % edg_x)) % 6.28318f) * rad, Mathf.Cos((reg * (x % edg_x)) % 6.28318f) * rad, rightPos + y * _len);//计算顶点坐标
                normals[i] = new Vector3(verts[i].x, verts[i].y, 0);//法线方向
                int id = x % (edg_x + 1) * 6 + y * edg_x * 6;
                if (x < edg_x + 1 && y < edg_y - 1 && (id + 5) < trians.Length)//计算顶点数组
                {
                    if (length > 0)
                    {
                        trians[id] = i;
                        trians[id + 1] = trians[id + 4] = i + edg_x + 1;
                        trians[id + 2] = trians[id + 3] = i + 1;
                        trians[id + 5] = i + edg_x + 2;
                    }
                    else
                    {
                        trians[id] = i;
                        trians[id + 1] = trians[id + 3] = i + 1;
                        trians[id + 2] = trians[id + 5] = i + edg_x + 1;
                        trians[id + 4] = i + edg_x + 2;
                    }

                }
                //if (edg_x != 2)//计算UV,考虑到2个边的情况
                //    uvs[i] = new Vector2(x == edg_x ? 1f : quaduvStep.x * x, y == edg_y - 1 ? (2*rad+len)/totalLen : quaduvStep.y * y);
                //else
                //    uvs[i] = new Vector2(x % edg_x, y == edg_y - 1 ? (2 * rad + len) / totalLen : quaduvStep.y * y);
            }

        //原点一面
        int maxId = edg_x * (edg_y - 1) * 6;
        verts[_deglen] = new Vector3(0, 0, rightPos);
        normals[_deglen] = -Vector3.forward;
        //uvs[_deglen] = new Vector2(0.5f, (rad) / totalLen);
        for (int x = 0; x < edg_x + 1; x++)
        {
            verts[_deglen + 1 + x] = new Vector3(Mathf.Sin((reg * (x % edg_x)) % 6.28318f) * rad, Mathf.Cos((reg * (x % edg_x)) % 6.28318f) * rad, rightPos);
            normals[_deglen + 1 + x] = -Vector3.forward;
            if (x == edg_x) continue;

            if (length > 0)
            {
                trians[3 * x + maxId] = _deglen;
                trians[3 * x + 1 + maxId] = _deglen + 1 + x;
                trians[3 * x + 2 + maxId] = _deglen + 2 + x;
            }
            else
            {
                trians[3 * x + maxId] = _deglen;
                trians[3 * x + 1 + maxId] = _deglen + 2 + x;
                trians[3 * x + 2 + maxId] = _deglen + 1 + x;
            }
        }

        //远点一面
        maxId += 3 * edg_x;
        verts[_deglen + 2 + edg_x] = new Vector3(0, 0, leftPos);
        normals[_deglen + 2 + edg_x] = Vector3.forward;
        //uvs[_deglen + 1] = new Vector2(0.5f, (3 * rad + len) / totalLen);

        for (int x = 0; x < edg_x + 1; x++)
        {
            verts[1 + x + edg_x + 2 + _deglen] = new Vector3(Mathf.Sin((reg * (x % edg_x)) % 6.28318f) * rad, Mathf.Cos((reg * (x % edg_x)) % 6.28318f) * rad, leftPos);
            normals[1 + x + edg_x + 2 + _deglen] = Vector3.forward;
            if (x == edg_x) continue;
            if (length > 0)
            {
                trians[3 * x + maxId] = _deglen + 2 + edg_x;
                trians[3 * x + 1 + maxId] = _deglen + 2 + edg_x + x + 2;
                trians[3 * x + 2 + maxId] = _deglen + 2 + edg_x + x + 1;
            }
            else
            {
                trians[3 * x + maxId] = _deglen + 2 + edg_x;
                trians[3 * x + 1 + maxId] = _deglen + 2 + edg_x + x + 1;
                trians[3 * x + 2 + maxId] = _deglen + 2 + edg_x + x + 2;
            }
        }
        mesh.Clear();
        mesh.vertices = verts;
        mesh.triangles = trians;
        //mesh.uv = uvs;
        mesh.normals = normals;
        mesh.RecalculateBounds();
    }

图腾效果图

Partical System(传送门、图腾)插图(9)

详细参数

Partical System(传送门、图腾)插图(10)

Partical System(传送门、图腾)插图(11)

Partical System(传送门、图腾)插图(12)

Partical System(传送门、图腾)插图(13)

Partical System(传送门、图腾)插图(14)

Partical System(传送门、图腾)插图(15)

Partical System(传送门、图腾)插图(16)

Partical System(传送门、图腾)插图(17)

Partical System(传送门、图腾)插图(18)

Partical System(传送门、图腾)插图(19)

Partical System(传送门、图腾)插图(20)

Partical System(传送门、图腾)插图(21)

Partical System(传送门、图腾)插图(22)

Partical System(传送门、图腾)插图(23)

Partical System(传送门、图腾)插图(24)

发表评论