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的时候,他的三角面顶点绘制顺序正好相反,所以需要在代码块中判断下。以上就是对代码绘制圆柱体的实现。希望对你有帮助。

(0)

相关推荐

  • Unity3D网格功能生成球体网格模型

    本文实例为大家分享了Unity3D网格功能生成球体网格模型的具体代码,供大家参考,具体内容如下 前面已经讲过怎样使用mesh生成一个自己的网格,那么本文将会讲述怎样将这个网格变换成自己想要的形状,比如一个球体. 我们需要知道一个从平面坐标到球体坐标的映射公式.假设平面坐标是(x,y),球体坐标是(x0,y0,z0),则 球体坐标(x0,y0,z0)可以通过以下代码得到,(x,y) 对应vertices[i].x和vertices[i].y. v.x = r * Mathf.Cos(vertice

  • Unity3D自定义创建圆锥体

    前言 这几天琢磨着开发个个人作品的时候,发现原来Unity3D官方没有提供圆锥体的创建功能,就自己做了个编辑器扩展.鉴于之前搜索Mesh编程的时候很少有博客把自己的算法讲清楚,这里我抛砖引玉,尽我所能为一些初学者提供参考,当然,算法未必优,如有更好的算法并乐意知会我则不胜感激,我是大龄转行Unity3D开发,一路行来都是自己琢磨,比较辛苦,先行谢过. 软件环境 Win10 + Unity3D 2017.3.0f3 正文 基本思路是以原点为圆锥体底部圆的中心点,以其正上方1单元处的点为圆锥体锥尖顶

  • Unity3D创建圆柱体的方法

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

  • asp.net实现数据从DataTable导入到Excel文件并创建表的方法

    本文实例讲述了asp.net实现数据从DataTable导入到Excel文件并创建表的方法.分享给大家供大家参考,具体如下: /// <summary> /// 把数据从DataTable导入到Excel文件里 /// </summary> /// <param name="dataTable">数据源</param> /// <param name="AbsoluteExcelFilePath">Exce

  • navicat不能创建函数解决方法分享

    第一次写MySQL FUNCTION,一直报错, Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '`company_id` int) RETURNS varchar(20) CHARSET utf8 BEGIN 本来的函数: CREATE DEFINER

  • jQuery简单创建节点的方法

    本文实例讲述了jQuery简单创建节点的方法.分享给大家供大家参考,具体如下: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script type="text/javascript" src="js/jquery-1

  • js中匿名函数的创建与调用方法分析

    本文实例分析了js中匿名函数的创建与调用方法.分享给大家供大家参考.具体实现方法如下: 匿名函数就是没有名字的函数了,也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数.最经常用作回调函数(callback)参数的值,很多新手朋友对于匿名函数不了解.这里就来分析一下. function 函数名(参数列表){函数体;} 如果是创建匿名函数,那就应该是: function(){函数体;} 因为是匿名函数,所以一般也不会有参数传给他. 为什么要创建匿名函数呢?在什么情况下会使用到匿

  • python类:class创建、数据方法属性及访问控制详解

    在Python中,可以通过class关键字定义自己的类,然后通过自定义的类对象类创建实例对象. python中创建类 创建一个Student的类,并且实现了这个类的初始化函数"__init__": class Student(object):     count = 0     books = []     def __init__(self, name):         self.name = name 接下来就通过上面的Student类来看看Python中类的相关内容. 类构造和

  • Python创建对称矩阵的方法示例【基于numpy模块】

    本文实例讲述了Python创建对称矩阵的方法.分享给大家供大家参考,具体如下: 对称(实对称)矩阵也即: step 1:创建一个方阵 >>> import numpy as np >>> X = np.random.rand(5**2).reshape(5, 5) >>> X array([[ 0.26984148, 0.25408384, 0.12428487, 0.0194565 , 0.91287708], [ 0.31837673, 0.354

  • Laravel5.1数据库连接、创建数据库、创建model及创建控制器的方法

    本文实例讲述了Laravel5.1数据库连接.创建数据库.创建model及创建控制器的方法.分享给大家供大家参考,具体如下: 前言:laravel创建数据库,实际可以手动创建,如古老的phpmyadmin 等均可以. 一.数据库连接: 在根目录(laravel5.1下面有个.env文件,如果没有则会有个.env.example然后将此文件修改成.env文件即可) 打开文件: 找到: DB_HOST=127.0.0.1 //连接地址不使用localhost DB_DATABASE=homestea

  • php创建session的方法实例详解

    本文实例讲述了php创建session的方法.分享给大家供大家参考.具体分析如下: 保存session只需要两个步骤,开启session和保存session数据.默认情况下,session保存在服务器端 c:\windows\temp文件夹下(保存的路径可以在php.ini文件中修改:开启session.save_path,填写上保存的路径即可). session创建代码 复制代码 代码如下: <?php echo "------如何保存 session 数据---------<br

  • Yii2创建控制器(createController)方法详解

    本文实例讲述了Yii2创建控制器(createController)方法.分享给大家供大家参考,具体如下: yii中创建控制器的是在application中的request通过UrlManager解析得出路由信息的,然后再由yii\base\Module中的 public function runAction($route, $params = []) 方法来创建控制器,最后由控制器再执行相应的动作. 首先得明确,Yii中的路由分三种情况: 第一种是带有模块的(module id/control

随机推荐