Unity3D创建圆柱体的方法

 更新时间:2019年02月22日 09:09:35   作者:JayW就是我吖  
这篇文章主要为大家详细介绍了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的时候,他的三角面顶点绘制顺序正好相反,所以需要在代码块中判断下。以上就是对代码绘制圆柱体的实现。希望对你有帮助。

相关文章

  • C#使用post发送和接收数据的方法

    C#使用post发送和接收数据的方法

    这篇文章主要介绍了C#使用post发送和接收数据的方法,涉及C#使用post收发数据的相关技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • C#中委托用法

    C#中委托用法

    这篇文章主要介绍了C#中委托用法,实例分析了C#的定义与使用技巧,需要的朋友可以参考下
    2015-05-05
  • C#中属性(Attribute)的用法

    C#中属性(Attribute)的用法

    这篇文章介绍了C#中属性(Attribute)的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C#关机小程序源码

    C#关机小程序源码

    这是用所学习的C#做的一个关机小程序,功能不多,只是为了练手,需要的朋友可以参考下
    2012-10-10
  • C#程序最小化到托盘图标操作步骤与实现代码

    C#程序最小化到托盘图标操作步骤与实现代码

    设置窗体属性showinTask=false;加notifyicon控件notifyIcon1,为控件notifyIcon1的属性Icon添加一个icon图标;添加窗体最小化事件(首先需要添加事件引用)接下来介绍实现代码,感兴趣的朋友可以研究下
    2012-12-12
  • C#回收机制之资源回收托管

    C#回收机制之资源回收托管

    这篇文章介绍了C#回收机制之资源回收托管,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C#实现打印与打印预览功能的思路及代码

    C#实现打印与打印预览功能的思路及代码

    这篇文章主要介绍了C#实现打印与打印预览功能的思路及代码,有需要的朋友可以参考一下
    2013-12-12
  • C#实现文件分割和合并的示例详解

    C#实现文件分割和合并的示例详解

    这篇文章主要为大家详细介绍了如何利用C#实现文件分割和合并的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • 详解C#如何使用WASM跨语言调用

    详解C#如何使用WASM跨语言调用

    WebAssembly(简称Wasm)是一种用于基于堆栈的虚拟机的二进制指令格式,这篇文章主要介绍了C#如何使用WASM跨语言调用,需要的小伙伴可以了解一下
    2023-08-08
  • C#实现可捕获几乎所有键盘鼠标事件的钩子类完整实例

    C#实现可捕获几乎所有键盘鼠标事件的钩子类完整实例

    这篇文章主要介绍了C#实现可捕获几乎所有键盘鼠标事件的钩子类,以完整实例形式分析了C#捕获键盘鼠标事件的钩子操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2016-06-06

最新评论