Unity3D开发之代码创建圆柱体

看到这篇文章你可能好奇unity自带圆柱体组件,直接就可以生成,为什么我们还要用代码生成。其实是最近领导对项目有一个要求,就是我们要在自写编辑器内操作圆管,也就是圆柱体。功能类似3DMax里的拉伸管线。刚开始看到这个要求我内心是拒绝的,mmp我是unity程序员不是图像学程序员啊,这看着有点底层啊。但是心想,这也是自我学习提升的机会,于是我就给领导个面子将它实现吧。我们知道如果想像3Dmax里那样操作管线,就必须用代码创建圆柱体并用代码控制他的顶点位置才能实现我们的需求。所以第一步就是用代码创建我们需要的圆柱体。实现的效果如下:

其实之前我自己尝试了解创建立方体的代码,看着很简单,其实也不简单,主要是对顶点,以及对应组成三角面顶点顺序的设置。我在网上搜到一篇自写圆柱体的代码,看着不错,直接复制来了,但是他提供的少两个面。所以需要我们自己去补上这个面。然后很重要的一点是两个面的交点不可以共用,必须再添加一次,因为涉及到法线的问题

//圆柱体是由两个圆和一个长方形组成的  先输入长方形的顶点 然后在输入圆顶点
    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();
    }

其实看代码会发现这个圆柱体的长度len是由我们自己声明的变量leftPos-rightPos获得的。即length=len=leftPos-rightPos。我们可以操作变量leftPos和rightPos来控制圆柱一端的位置以及其长度。当我们length<0的时候,他的三角面顶点绘制顺序正好相反,所以需要在代码块中判断下。以上就是对代码绘制圆柱体的实现。希望对你有帮助。

猜你喜欢

转载自blog.csdn.net/qq_33994566/article/details/81101534