Unity中用Mesh画一个圆环(二)
中目标-生成完整面
在之前的内容中我们已经成功生成了一个面,接下来我们要生成剩下的面就很容易了。
我们把之前生成的面当作顶面,接着我们来生成底面。
还记得前面说过\(\color{#1E90FF}{Depth}\)这个参数用来控制深度,也就是顶面和地面之间的距离,放到坐标系中就是控制Z的位置。
底面和顶面的顶点生成方法是一样的,唯一不同的地方就是Z轴的不同。 我们只要用生成顶面的方法改下Z坐标,就可以得到底面了。
//下
for (int i = 0; i <= NumberOfSides; i++)
{
float angle = 180 - i * incrementAngle;
float innerX = (Radius - Thickness) * Mathf.Cos(angle * Mathf.Deg2Rad);
float innerY = (Radius - Thickness) * Mathf.Sin(angle * Mathf.Deg2Rad);
vertexList.Add(new Vector3(innerX, innerY, -1 * Depth / 2));
float outsideX = Radius * Mathf.Cos(angle * Mathf.Deg2Rad);
float outsideY = Radius * Mathf.Sin(angle * Mathf.Deg2Rad);
vertexList.Add(new Vector3(outsideX, outsideY, - 1 * Depth / 2));
}
三角形索引的生成和之前也是一样的,不同的是一开始的方向,因为顶面的法线是向上的,而底面的法线是向下的:
direction = 1;
startIndex += (NumberOfSides + 1) * 2;
for (int i = 0; i < NumberOfSides * 2; i++)
{
int[] triangleIndexs = getTriangleIndexs(i, direction, startIndex);
direction *= -1;
for (int j = 0; j < triangleIndexs.Length; j++)
{
triangleList.Add(triangleIndexs[j]);
}
}
至于UV索引则设置和顶面的一样即可。
其实生成顶面和底面之后,大部分的工作已经完成了,这时候我们已经生成了我们需要的所有顶点。前后左右也只是用现有的这些顶点进行生成。
我们前面生成的圆柱体是基于圆生成的,如果我们改成基于贝塞尔生成的那也是可以的。
修改方法很简单,就是改下生成顶点时的过程就好了,其他的不需要动。
具体过程直接看代码吧,包看包懂。
当然下面的代码是为了方面理解所以写得冗余,如果用到项目中建议优化下,不然会被主程打的。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//[RequireComponent(typeof(MeshFilter))]
//[RequireComponent(typeof(MeshRenderer))]
[ExecuteInEditMode]
public class DrawArch : MonoBehaviour
{
public float Radius = 20.0f; //外圈的半径
public float Thickness = 10.0f; //厚度,外圈半径减去内圈半径
public float Depth = 1.0f; //厚度
public int NumberOfSides = 30; //由多少个面组成
public float DrawArchDegrees = 90.0f; //要绘画多长
public Vector2[] bezierPoints = new Vector2[4];
public Material archMaterial = null;
private int VertexCountOneSide = 0; //生成一面所需的顶点数
private Mesh mesh = null;
private float incrementAngle = 0;
private List<Vector3> vertexList = new List<Vector3>();
private List<int> triangleList = new List<int>();
private List<Vector2> uvList = new List<Vector2>();
// Start is called before the first frame update
void Start()
{
mesh = new Mesh();
}
void GenerateMesh()
{
VertexCountOneSide = (NumberOfSides + 1) * 2;
incrementAngle = DrawArchDegrees / NumberOfSides;
GenerateVertex();
GenerateTriangleIndex();
GenerateUV();
mesh.vertices = vertexList.ToArray();
mesh.uv = uvList.ToArray();
mesh.triangles = triangleList.ToArray();
mesh.RecalculateNormals();
gameObject.GetComponent<MeshFilter>().mesh = mesh;
gameObject.GetComponent<MeshRenderer>().material = archMaterial;
}
//生成顶点坐标
void GenerateVertex()
{
//上
vertexList.Clear();
for (int i = 0; i <= NumberOfSides; i++)
{
//float[] points = GetCirclePoint(Radius - Thickness, i);
//vertexList.Add(new Vector3(points[0], points[1], Depth / 2));
//points = GetCirclePoint(Radius, i);
//vertexList.Add(new Vector3(points[0], points[1], Depth / 2));
float[] points = GetBezierPoint(i);
vertexList.Add(new Vector3(points[0], points[1], Depth / 2));
points = GetBezierPoint(i);
vertexList.Add(new Vector3(points[0] - 1, points[1], Depth / 2));
}
//下
for (int i = 0; i <= NumberOfSides; i++)
{
//float[] points = GetCirclePoint(Radius - Thickness, i);
//vertexList.Add(new Vector3(points[0], points[1], -1 * Depth / 2));
//points = GetCirclePoint(Radius, i);
//vertexList.Add(new Vector3(points[0], points[1], -1 * Depth / 2));
float[] points = GetBezierPoint(i);
vertexList.Add(new Vector3(points[0], points[1], -1 * Depth / 2));
points = GetBezierPoint(i);
vertexList.Add(new Vector3(points[0] - 1, points[1], -1 * Depth / 2));
}
//前
for (int i = 0; i <= NumberOfSides * 2 ; i += 2)
{
vertexList.Add(vertexList[i]);
vertexList.Add(vertexList[i + VertexCountOneSide]);
}
//后
for (int i = 0; i <= NumberOfSides * 2; i += 2)
{
vertexList.Add(vertexList[i + 1]);
vertexList.Add(vertexList[i + VertexCountOneSide + 1]);
}
//左
vertexList.Add(vertexList[0]);
vertexList.Add(vertexList[1]);
vertexList.Add(vertexList[VertexCountOneSide + 0]);
vertexList.Add(vertexList[VertexCountOneSide + 1]);
//右
vertexList.Add(vertexList[VertexCountOneSide -2]);
vertexList.Add(vertexList[VertexCountOneSide - 1]);
vertexList.Add(vertexList[VertexCountOneSide * 2 - 2]);
vertexList.Add(vertexList[VertexCountOneSide * 2 - 1]);
}
void GenerateTriangleIndex()
{
//三角形索引
triangleList.Clear();
//上
int direction = -1;
int startIndex = 0;
for (int i = 0; i < NumberOfSides * 2; i++)
{
int[] triangleIndexs = getTriangleIndexs(i, direction);
direction *= -1;
for (int j = 0; j < triangleIndexs.Length; j++)
{
triangleList.Add(triangleIndexs[j]);
}
}
//下
direction = 1;
startIndex += (NumberOfSides + 1) * 2;
for (int i = 0; i < NumberOfSides * 2; i++)
{
int[] triangleIndexs = getTriangleIndexs(i, direction, startIndex);
direction *= -1;
for (int j = 0; j < triangleIndexs.Length; j++)
{
triangleList.Add(triangleIndexs[j]);
}
}
//前
direction = 1;
startIndex += VertexCountOneSide;
for (int i = 0; i < NumberOfSides * 2; i++)
{
int[] triangleIndexs = getTriangleIndexs(i, direction, startIndex);
direction *= -1;
for (int j = 0; j < triangleIndexs.Length; j++)
{
triangleList.Add(triangleIndexs[j]);
}
}
//后
direction = -1;
startIndex += VertexCountOneSide;
for (int i = 0; i < NumberOfSides * 2; i++)
{
int[] triangleIndexs = getTriangleIndexs(i, direction, startIndex);
direction *= -1;
for (int j = 0; j < triangleIndexs.Length; j++)
{
triangleList.Add(triangleIndexs[j]);
}
}
startIndex += VertexCountOneSide;
//左
triangleList.Add(startIndex + 0);
triangleList.Add(startIndex + 1);
triangleList.Add(startIndex + 2);
triangleList.Add(startIndex + 3);
triangleList.Add(startIndex + 2);
triangleList.Add(startIndex + 1);
//右
triangleList.Add(startIndex + 4 + 2);
triangleList.Add(startIndex + 4 + 1);
triangleList.Add(startIndex + 4 + 0);
triangleList.Add(startIndex + 4 + 1);
triangleList.Add(startIndex + 4 + 2);
triangleList.Add(startIndex + 4 + 3);
}
//UV索引
void GenerateUV()
{
uvList.Clear();
//上
for (int i = 0; i <= NumberOfSides; i++)
{
float angle = 180 - i * incrementAngle;
float littleX = (1.0f / NumberOfSides) * i;
uvList.Add(new Vector2(littleX, 0));
float bigX = (1.0f / NumberOfSides) * i;
uvList.Add(new Vector2(bigX, 1));
}
//下
for (int i = 0; i <= NumberOfSides; i++)
{
float angle = 180 - i * incrementAngle;
float littleX = (1.0f / NumberOfSides) * i;
uvList.Add(new Vector2(littleX, 0));
float bigX = (1.0f / NumberOfSides) * i;
uvList.Add(new Vector2(bigX, 1));
}
//前
for (int i = 0; i <= NumberOfSides; i++)
{
float angle = 180 - i * incrementAngle;
float littleX = (1.0f / NumberOfSides) * i;
uvList.Add(new Vector2(littleX, 0));
float bigX = (1.0f / NumberOfSides) * i;
uvList.Add(new Vector2(bigX, 1));
}
//后
for (int i = 0; i <= NumberOfSides; i++)
{
float angle = 180 - i * incrementAngle;
float littleX = (1.0f / NumberOfSides) * i;
uvList.Add(new Vector2(littleX, 0));
float bigX = (1.0f / NumberOfSides) * i;
uvList.Add(new Vector2(bigX, 1));
}
//左
uvList.Add(new Vector2(1.0f, 1.0f));
uvList.Add(new Vector2(0.0f, 1.0f));
uvList.Add(new Vector2(0.0f, 0.0f));
uvList.Add(new Vector2(1.0f, 0.0f));
//右
uvList.Add(new Vector2(1.0f, 1.0f));
uvList.Add(new Vector2(0.0f, 1.0f));
uvList.Add(new Vector2(0.0f, 0.0f));
uvList.Add(new Vector2(1.0f, 0.0f));
}
int[] getTriangleIndexs(int index, int direction, int startIndex = 0)
{
int[] triangleIndexs = new int[3] { 0+ startIndex, 1 + startIndex, 2 + startIndex };
for (int i = 0; i < triangleIndexs.Length; i++)
{
triangleIndexs[i] += index;
}
if (direction == -1)
{
int temp = triangleIndexs[0];
triangleIndexs[0] = triangleIndexs[2];
triangleIndexs[2] = temp;
}
return triangleIndexs;
}
private void Update()
{
GenerateMesh();
}
float[] GetCirclePoint(float radius, int index)
{
float angle = 180 - index * incrementAngle;
float[] points = new float[2];
float x = radius * Mathf.Cos(angle * Mathf.Deg2Rad);
float y = radius * Mathf.Sin(angle * Mathf.Deg2Rad);
points[0] = x;
points[1] = y;
return points;
}
float[] GetBezierPoint(int index)
{
float t = 1.0f / (NumberOfSides + 1) * index;
float[] points = new float[2];
var vec = Bezier(bezierPoints[0], bezierPoints[1], bezierPoints[2], bezierPoints[3], t);
points[0] = vec.x;
points[1] = vec.y;
return points;
}
Vector2 Bezier(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3, float t)
{
Vector2 result;
Vector2 p0p1 = (1 - t) * p0 + t * p1;
Vector2 p1p2 = (1 - t) * p1 + t * p2;
Vector2 p2p3 = (1 - t) * p2 + t * p3;
Vector2 p0p1p2 = (1 - t) * p0p1 + t * p1p2;
Vector2 p1p2p3 = (1 - t) * p1p2 + t * p2p3;
result = (1 - t) * p0p1p2 + t * p1p2p3;
return result;
}
}
Unity中用Mesh画一个圆环(二)的更多相关文章
- Unity中用Mesh画一个圆环
Probuider 前几天在做一个小项目的时候,用到了Unity自带的一个包ProBuilder其中的Arch生成1/4圆. 挺好玩的,可以在直接Unity中根据需要用Mesh定制生成图形,而不用建模 ...
- Unity3D UGUI Shader画一个圆环
Shader "Unlit/NewUnlitShader" { Properties { _MainTex ("Texture", 2D) = "wh ...
- Directx11学习笔记【十二】 画一个旋转的彩色立方体
上一次我们学习了如何画一个2D三角形,现在让我们进一步学习如何画一个旋转的彩色立方体吧. 具体流程同画三角形类似,因此不再给出完整代码了,不同的部分会再说明. 由于我们要画彩色的立方体,所以顶点结构体 ...
- 如何用Photoshop画一个发光金币(unity游戏素材教程)
做好的发光金币预览图: 以下为如何用Photoshop画一个发光金币教程: [1]如上图1-2,新建,名称改为Coin,宽度20像素,高度20像素,分辨率72,背景白色: [2]使用Alt+Shift ...
- Java坦克大战 (二) 之画一个能动的圆圈代表坦克
本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...
- Unity中Mesh分解与边缘高亮加上深度检测
一个比较简单的需求,不过遇到些坑,记录下. 房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMe ...
- unity, editable mesh
一,需求 从fbx载入的模型是不可以在unity里编辑的. 我有一人特殊的需求就是想在unity里为mesh的各顶点K动画. 于是需要自己实现一个可编辑(其实只是顶点可以拖动)的mesh. 二,思路 ...
- iOS圆形图片裁剪,以及原型图片外面加一个圆环
废话不多说,直接上代码 #import "ViewController.h" @interface ViewController () @property (nonatomic,s ...
- 用PS画一个齿轮
以前只会画圆画方,这没技术含量.今天学了一个稍难一点的,画一个齿轮.图形有圆也有方.以下描述如何画出来的. 一.打开PS准备一画布,画一矩形并且填充颜色. 二.编辑->自由变换(CTRL+T), ...
随机推荐
- Numpy中的三个常用正态分布相关的函数,randn,standard_normal, normal的区别
这三个函数都可以返回随机正态分布(高斯Gaussian 分布)的数组,都可以从numpy.random中导出 先看三个函数的参数方式: randn: randn(d0, d1, ..., dn), 返 ...
- Cobalt Strike之信息收集、木马钓鱼
System Profiler使用 System Profiler 模块,搜集目标的各类机器信息(操作系统版本,浏览器版本等) Attacks->web drive-by->System ...
- Python3之多线程学习
这里做一个自己复习多线程的笔记 Python中使用线程有两种方式:函数或者用类来包装线程对象. 函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程.语法如下: ...
- socat的介绍与使用
Socat 是 Linux 下的一个多功能的网络工具,名字来由是 「Socket CAT」.其功能与有瑞士军刀之称的 Netcat 类似,可以看做是 Netcat 的加强版. Socat 的主要特点就 ...
- PMBOK(第六版) PMP笔记——《十三》第十三章(项目干系人管理)
PMBOK(第六版) PMP笔记——<十三>第十三章(项目干系人管理) 第十三章 项目干系人管理: 了解干系人的需要和期望.解决实际发生的问题.管理利益冲突.促进干系人合理参与 项目决策和 ...
- 自力更生Collections.sort发现比较结果混乱?Comparator的锅还是强转类型导致?
近日开发任务时间充裕一些,于是有时间回顾一下项目. 我关注到了项目中使用的七牛云的对象存储服务. 作为测试需要上传了一些图片,但七牛的控制台却无法将内容按照上传时间排序或者是按照日期查询,由于buck ...
- [Abp vNext 源码分析] - 11. 用户的自定义参数与配置
一.简要说明 文章信息: 基于的 ABP vNext 版本:1.0.0 创作日期:2019 年 10 月 23 日晚 更新日期:暂无 ABP vNext 针对用户可编辑的配置,提供了单独的 Volo. ...
- 面试必问:ACID/CAP
转载: https://www.jdon.com/artichect/acid-cap.html ACID和CAP的详尽比较 事务机制ACID和CAP理论是数据管理和分布式系统中两个重要的概念,很不巧 ...
- Windows下NFS服务器SFU设置(可以共享linux系统)
一.安装SFU1.下载软件SFU http://download.microsoft.com/download/a/1/c/a1ca7af1-a6e3-46e7-874a-4c5d8c0fb3b7/S ...
- ansible模块之command、shell、script、file、copy、fetch
前戏 ansible 批量在远程主机上执行命令 openpyxl 操作excel表格 puppet ansible slatstack ansible epel源 第一步: 下载epel源 wget ...