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), ...
随机推荐
- 由一次线上故障来理解下 TCP 三握、四挥 & Java 堆栈分析到源码的探秘
本文导读: 生产故障场景介绍 TCP 建连三次握手过程 TCP 断连四次挥手过程 结合 Java 堆栈剖析源码 再从堆栈中找到"罪魁祸首" 问题优化方案总结 1.生产故障场景介绍 ...
- django-drf框架中排序和查询组件
0910自我总结 django-drf框架中排序和查询组件 一查询相关 1.模糊查询 1.导入模块组件 from rest_framework.filters import SearchFilter ...
- phpstorm 设置换行符的格式
菜单 > 文件 > 设置
- 网站开发常用Sql语句
维护网站,经常操作数据库,使用sql语句可以达到事半功倍的效果.比如,把所有密码为空的教师初始设成id一致,sql语句比手动快万倍. 下面介绍数据库开发中经常用到的一些sql语句: 一 建库操作 1. ...
- MacOS访达增强工具-TotalFinder
TotalFinder 是Mac上最好用的Finder增强工具,TotalFinder 提供了多标签式浏览.拷贝路径.剪切文件.显示隐藏文件.双栏窗口模式.彩色标签等功能 彩色的标签 将彩色带回El ...
- .gitignore实现忽略提交
- 1.Linux-CentOS7.6安装教程
了解Linux Linux 就是一个操作系统,主要为企业提供支持与服务. 学习Linux需要具备什么基础?能看懂中文,能看懂简单的 English 1.什么是Linux? Linux:和我们常见的 ...
- uni-app 请求封装
1.创建一个http.js const baseUrl = 'http://192.168.1.188:8080'; const httpRequest = (opts, data) => ...
- 拨云见日,彻底弄清楚Java日志框架 log4j, logback, slf4j的区别与联系
log4j 以及 logback, slf4j 官网 日志框架的困惑 作为一个正常的项目,是必须有日志框架的存在的,没有日志,很难追踪一些奇奇怪怪的系统问题. 但是,我们经常在项目的依赖中,见到奇奇怪 ...
- JVM(1) Java内存区域
对于Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,不容易出现内存泄漏和内存溢出问题.不过,也正是因为Java程序员把内存控制的权 ...