之前我们介绍了如何绘制一个三角形的Mesh。今天讲解一下如何绘制一个圆形的Mesh。

Unity3D中Mesh的基本单位是三角形,而圆形就是由许许多多的三角形组成的。那么我们就知道了绘制圆形的Mesh需要两个变量

 public float Radius = 5;   //半径public int Segments = 50;  //分割数

先加上基本的代码

[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class TestCircle : MonoBehaviour {public float Radius = 5;  //半径public int Segments = 50;  //分割数private MeshFilter meshFilter;void Awake(){meshFilter = GetComponent<MeshFilter>();meshFilter.mesh = CreateMesh(Radius, Segments);}Mesh CreateMesh(float radius, int segments){Mesh mesh = new Mesh ();return mesh;}
}

那么CreateMesh这个方法要怎么实现呢?

首先是vertices(顶点)

     int vlen = 1 + segments;Vector3[] vertices = new Vector3[vlen];vertices[0] = Vector3.zero;float angleDegree = 360;float angle = Mathf.Deg2Rad * angleDegree;float currAngle = angle / 2;float deltaAngle = angle / segments;for (int i = 1; i < vlen; i++){float cosA = Mathf.Cos(currAngle);float sinA = Mathf.Sin(currAngle);vertices[i] = new Vector3 (cosA * radius, 0, sinA * radius);currAngle -= deltaAngle;}

vertices[0]保存圆心坐标,后面的segments个Vector3保存圆(边)上的点。

接着是triangles(三角形),里面实际保存的是vertices的下标

     int tlen = segments * 3;int[] triangles = new int[tlen];for (int i = 0, vi = 1; i < tlen - 3; i += 3, vi++){triangles[i] = 0;triangles[i + 1] = vi;triangles[i + 2] = vi + 1;}triangles [tlen - 3] = 0;triangles [tlen - 2] = vlen - 1;triangles [tlen - 1] = 1;

为了完成闭环,将最后一个三角形单独拎出来。

需要注意的是:三角形必须是顺时针取顶点。

最后是uv(纹理坐标),不太理解是什么的,可以先看一下之前的博文:为三角形添加纹理

     Vector2[] uvs = new Vector2[vlen];for (int i = 0; i < vlen; i++){uvs [i] = new Vector2 (vertices[i].x / radius / 2 + 0.5f, vertices[i].z / radius / 2 + 0.5f);}

最后把属性赋给mesh就可以了

     mesh.vertices = vertices;mesh.triangles = triangles;mesh.uv = uvs;

我们测试一下,导入一张图片

我特意找了一张圆外不透明的图片。

新建一个material,shader使用Unlit/Texture,选择这张图片作为纹理。

新建一个GameObject,添加TestCircel作为组件,讲MeshRenderer的Material设置为新建的material。

点击运行,就可以看到圆了。

接下来稍微提升一下难度:假如我需要一个圆环Mesh怎么办?

圆形是由segments个等腰三角形组成的,圆环就是有segments个等腰梯形组成的。

那么等腰梯形由什么组成?两个三角形(多个也是可以的)。

首先添加一个变量,内圆半径

public float InnerRadius = 3;   //内圆半径

CreateMesh方法也相应的增加了一个参数。

vertices(顶点)

     int vlen = segments * 2 + 2;Vector3[] vertices = new Vector3[vlen];float angleDegree = 360;float angle = Mathf.Deg2Rad * angleDegree;float currAngle = angle / 2;float deltaAngle = angle / segments;for (int i = 0; i < vlen; i+=2){float cosA = Mathf.Cos(currAngle);float sinA = Mathf.Sin(currAngle);vertices[i] = new Vector3 (cosA * innerRadius, 0, sinA * innerRadius);vertices[i + 1] = new Vector3 (cosA * radius, 0, sinA * radius);currAngle -= deltaAngle;}

每一个步长(2)保存梯形(非平行边)的两个顶点的坐标。我们为180度和-180度分别创建了两个值相等的点,是为了方便triangles的计算。

triangles(三角形)

     int tlen = segments * 6;int[] triangles = new int[tlen];for (int i = 0, vi = 0; i < tlen; i += 6, vi+=2){triangles[i] = vi;triangles[i + 1] = vi + 1;triangles[i + 2] = vi + 3;triangles[i + 3] = vi + 3;triangles[i + 4] = vi + 2;triangles[i + 5] = vi;}

把每个分割梯形再分割成两个三角形。仍然需要注意的是:三角形必须是顺时针取顶点。

uv(纹理坐标)代码不变

然后我们就得到了一个被打了马赛克的圆(误)

假如我们需要一个扇形/扇面怎么办?其实我已经预留好了修改的余地,把顶点代码片段里的

     float angleDegree = 360;

去掉,作为参数输入即可。InnerRadius=0就是扇形,InnerRadius>0就是扇面。

加上Gizmos,调整一下代码

using UnityEngine;
using System.Collections;[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class TestCircle : MonoBehaviour {public float Radius = 5;  //半径public int Segments = 50;  //分割数public float InnerRadius = 3; //内圆半径public float AngleDegree = 90;private CircleMeshCreator _creator = new CircleMeshCreator();private MeshFilter _meshFilter;void Awake(){_meshFilter = GetComponent<MeshFilter>();}void Update(){_meshFilter.mesh = _creator.CreateMesh(Radius, Segments, InnerRadius, AngleDegree);}void OnDrawGizmos(){Gizmos.color = Color.gray;DrawMesh();}void OnDrawGizmosSelected(){Gizmos.color = Color.green;DrawMesh();}private void DrawMesh(){Mesh mesh = _creator.CreateMesh(Radius, Segments, InnerRadius, AngleDegree);int[] tris = mesh.triangles;for (int i = 0; i < tris.Length; i+=3){Gizmos.DrawLine(TransformToWorld(mesh.vertices[tris[i]]), TransformToWorld(mesh.vertices[tris[i + 1]]));Gizmos.DrawLine(TransformToWorld(mesh.vertices[tris[i]]), TransformToWorld(mesh.vertices[tris[i + 2]]));Gizmos.DrawLine(TransformToWorld(mesh.vertices[tris[i+1]]), TransformToWorld(mesh.vertices[tris[i + 2]]));}}private Vector3 TransformToWorld(Vector3 src){return transform.TransformPoint(src);}private class CircleMeshCreator{private static readonly int PRECISION = 1000;private float _radius;private int _segments;private float _innerRadius;private float _angleDegree;private Mesh _cacheMesh ;public Mesh CreateMesh(float radius, int segments, float innerRadius, float angleDegree){if (checkDiff(radius, segments, innerRadius, angleDegree)){Mesh newMesh = Create(radius, segments, innerRadius, angleDegree);if (newMesh != null){_cacheMesh = newMesh;this._radius = radius;this._segments = segments;this._innerRadius = innerRadius;this._angleDegree = angleDegree;}}return _cacheMesh;}private Mesh Create(float radius, int segments, float innerRadius, float angleDegree){if (segments <= 0){segments = 1;#if UNITY_EDITORDebug.Log("segments must be larger than zero.");#endif}Mesh mesh = new Mesh();int vlen = segments * 2 + 2;Vector3[] vertices = new Vector3[vlen];float angle = Mathf.Deg2Rad * angleDegree;float currAngle = angle / 2;float deltaAngle = angle / segments;for (int i = 0; i < vlen; i+=2){float cosA = Mathf.Cos(currAngle);float sinA = Mathf.Sin(currAngle);vertices[i] = new Vector3 (cosA * innerRadius, 0, sinA * innerRadius);vertices[i + 1] = new Vector3 (cosA * radius, 0, sinA * radius);currAngle -= deltaAngle;}int tlen = segments * 6;int[] triangles = new int[tlen];for (int i = 0, vi = 0; i < tlen; i += 6, vi+=2){triangles[i] = vi;triangles[i + 1] = vi + 1;triangles[i + 2] = vi + 3;triangles[i + 3] = vi + 3;triangles[i + 4] = vi + 2;triangles[i + 5] = vi;}Vector2[] uvs = new Vector2[vlen];for (int i = 0; i < vlen; i++){uvs [i] = new Vector2 (vertices[i].x / radius / 2 + 0.5f, vertices[i].z / radius / 2 + 0.5f);}mesh.vertices = vertices;mesh.triangles = triangles;mesh.uv = uvs;return mesh;}private bool checkDiff(float radius, int segments, float innerRadius, float angleDegree){return segments != this._segments || (int)((angleDegree - this._angleDegree) * PRECISION) != 0 ||(int)((radius - this._radius) * PRECISION) != 0 || (int)((innerRadius - this._innerRadius) * PRECISION) != 0;}}}

恩,改成这样,应该命名为TestSector更为合适一点。

最后附上源码下载链接

Unity3D Mesh小课堂(三)圆形与圆环相关推荐

  1. 微信小程序 三 圆形图片

    圆形图片和圆形其它控件一样 home.wxss .profile{width: 50rpx;height: 50rpx;border: 0 solid #ff0000;border-radius: 1 ...

  2. 【机器视觉运动控制一体机小课堂】三分钟进行轮廓提取

    背景 轮廓提取是基于边缘轮廓的算法,可用于需要提取工件轮廓信息后进行加工处理的检测加工项目,可广泛应用于点胶.激光切割.工件打磨等需要提取工件轮廓的领域. 轮廓是一种能存储一系列点集的数据结构,可分为 ...

  3. 锚杆拉拔试验弹性模量计算_【安全宣教】煤亮子小课堂(十三)——锚杆的锚固力和拉拔力...

    每天学习一点点,每天进步一点点,<煤亮子"小"课堂>开讲了.在今天的节目里,掘进准备队副队长冯文军,与大家一起分享锚杆的锚固力和拉拔力. REC 今天的知识点是锚杆的锚 ...

  4. 宝付国际跨境知识小课堂 | 人民币外汇市场是个啥?

    全球化浪潮下,因为各个经济体的比较利益差异,产生了货物.服务.人员或资本之间的流动.各个经济体使用的当地货币不同,为了贸易或资本流动及其价值定价,本国的货币需要兑换成另一国的货币来结算,这个货币兑换的 ...

  5. 云原生小课堂|Envoy请求流程源码解析(三):请求解析

    ​ 前言 Envoy 是一款面向 Service Mesh 的高性能网络代理服务.它与应用程序并行运行,通过以平台无关的方式提供通用功能来抽象网络.当基础架构中的所有服务流量都通过 Envoy 网格时 ...

  6. 【视觉运控一体机小课堂】三分钟搭建机器视觉开发环境

    回顾之前课程正运动技术与大家分享了,VPLC系列机器视觉运动控制一体机快速入门和应用案例等系列课程. 今天,我们来讲解一下正运动技术VPLC系列控制器ZDevelop编程软件如何来建立ZVision软 ...

  7. 【机器视觉运动控制一体机小课堂】三分钟进行灰度匹配

    背景 不同的模板匹配方法,其操作步骤也不一样,其生成模板的方式也有不同的地方,在之前的课程中我们讲述了基于形状的模板匹配,本期课程我们去了解一下基于灰度值的模板匹配. 基于灰度值的模板匹配适用于图像内 ...

  8. 微信小程序 环形进度条_微信小程序实现圆形进度条实例分享

    本文主要和大家分享微信小程序实现圆形进度条实例,希望能帮助到大家. 小程序中使用圆形倒计时,效果图: 思路使用2个canvas 一个是背景圆环,一个是彩色圆环. 使用setInterval 让彩色圆环 ...

  9. 微信小程序之圆形进度条(自定义组件)

    前言 昨天在微信小程序实现了圆形进度条,今天想把这个圆形进度条做成一个组件,方便以后直接拿来用. 根据官方文档自定义组件一步一步来 创建自定义组件 第一步创建项目结构 打开微信开发者工具创建一个项目, ...

最新文章

  1. Navicat 9如何连接ORACLE10G数据库
  2. jquery删除数组中的某个元素下标越界_Java数据结构和算法(二)—数组
  3. JdbcTemplate类中的execute方法
  4. xilinx SoC学习笔记之PetaLinux
  5. ningbooj--1655--木块拼接(贪心)
  6. 135.002 智能合约设计-——多员工薪酬系统
  7. android源码解析------Media多媒体framework层分析
  8. 软件设计精要与模式(第2版)
  9. 我就是认真:Linux SWAP 深度解读(必须收藏)
  10. php编码怎么变西欧了403,你知道一个简单的PHP脚本在ip检查后抛出403吗?
  11. 传统车道线检测之黄白线、虚实车道线检测(附python代码)
  12. eleme饿了么vue项目随笔,随时更新,想到哪里写到哪里比较凌乱一直更新
  13. 从无刷直流电动机控制系统电磁兼容设计,谈电磁干扰原理
  14. 互斥锁、自旋锁、读写锁和文件锁
  15. css td 比例,CSS设置表格TD宽度布局
  16. dalao的背包九讲
  17. C#把月日年帶有 AM、PM的时间格式转换为正常时间格式
  18. 《孩子,你慢慢来》的读书笔记与读后感2600字
  19. Tecplot操作记录
  20. android开发指纹解锁,Android-指纹解锁技术

热门文章

  1. php把变量转换为字符串,php如何将变量转换成字符串
  2. 如何将Excel中的数据复制到CAD中?
  3. 张晨光老师高薪就业系列 面试之五 集锦
  4. 2019年1+X 证书 Web 前端开发中级理论考试——易错题、陌生但又会考到的题目原题+答案(文章含五套题的内容)
  5. 在移动硬盘上安装win to go(Windows 10)和Linux to go(ubantu)双系统
  6. 天宫一号将在酒泉发射
  7. 【杂项】通过Excel为字符串产生条码
  8. 阿里EasyExcel小数点精度问题和无故多了个.0
  9. Python爬虫实战,requests模块,爬虫采集网易财经股票交易数据
  10. 学习C语言基础(1)C程序模板