中目标-生成完整面

在之前的内容中我们已经成功生成了一个面,接下来我们要生成剩下的面就很容易了。

我们把之前生成的面当作顶面,接着我们来生成底面。

还记得前面说过\(\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画一个圆环(二)的更多相关文章

  1. Unity中用Mesh画一个圆环

    Probuider 前几天在做一个小项目的时候,用到了Unity自带的一个包ProBuilder其中的Arch生成1/4圆. 挺好玩的,可以在直接Unity中根据需要用Mesh定制生成图形,而不用建模 ...

  2. Unity3D UGUI Shader画一个圆环

    Shader "Unlit/NewUnlitShader" { Properties { _MainTex ("Texture", 2D) = "wh ...

  3. Directx11学习笔记【十二】 画一个旋转的彩色立方体

    上一次我们学习了如何画一个2D三角形,现在让我们进一步学习如何画一个旋转的彩色立方体吧. 具体流程同画三角形类似,因此不再给出完整代码了,不同的部分会再说明. 由于我们要画彩色的立方体,所以顶点结构体 ...

  4. 如何用Photoshop画一个发光金币(unity游戏素材教程)

    做好的发光金币预览图: 以下为如何用Photoshop画一个发光金币教程: [1]如上图1-2,新建,名称改为Coin,宽度20像素,高度20像素,分辨率72,背景白色: [2]使用Alt+Shift ...

  5. Java坦克大战 (二) 之画一个能动的圆圈代表坦克

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  6. Unity中Mesh分解与边缘高亮加上深度检测

    一个比较简单的需求,不过遇到些坑,记录下. 房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMe ...

  7. unity, editable mesh

    一,需求 从fbx载入的模型是不可以在unity里编辑的. 我有一人特殊的需求就是想在unity里为mesh的各顶点K动画. 于是需要自己实现一个可编辑(其实只是顶点可以拖动)的mesh. 二,思路 ...

  8. iOS圆形图片裁剪,以及原型图片外面加一个圆环

    废话不多说,直接上代码 #import "ViewController.h" @interface ViewController () @property (nonatomic,s ...

  9. 用PS画一个齿轮

    以前只会画圆画方,这没技术含量.今天学了一个稍难一点的,画一个齿轮.图形有圆也有方.以下描述如何画出来的. 一.打开PS准备一画布,画一矩形并且填充颜色. 二.编辑->自由变换(CTRL+T), ...

随机推荐

  1. 由一次线上故障来理解下 TCP 三握、四挥 & Java 堆栈分析到源码的探秘

    本文导读: 生产故障场景介绍 TCP 建连三次握手过程 TCP 断连四次挥手过程 结合 Java 堆栈剖析源码 再从堆栈中找到"罪魁祸首" 问题优化方案总结 1.生产故障场景介绍 ...

  2. django-drf框架中排序和查询组件

    0910自我总结 django-drf框架中排序和查询组件 一查询相关 1.模糊查询 1.导入模块组件 from rest_framework.filters import SearchFilter ...

  3. phpstorm 设置换行符的格式

    菜单 >  文件 > 设置

  4. 网站开发常用Sql语句

    维护网站,经常操作数据库,使用sql语句可以达到事半功倍的效果.比如,把所有密码为空的教师初始设成id一致,sql语句比手动快万倍. 下面介绍数据库开发中经常用到的一些sql语句: 一 建库操作 1. ...

  5. MacOS访达增强工具-TotalFinder

    TotalFinder 是Mac上最好用的Finder增强工具,TotalFinder 提供了多标签式浏览.拷贝路径.剪切文件.显示隐藏文件.双栏窗口模式.彩色标签等功能 彩色的标签 将彩色带回El ...

  6. .gitignore实现忽略提交

  7. 1.Linux-CentOS7.6安装教程

    了解Linux Linux 就是一个操作系统,主要为企业提供支持与服务. 学习Linux需要具备什么基础?能看懂中文,能看懂简单的 English ​ 1.什么是Linux? Linux:和我们常见的 ...

  8. uni-app 请求封装

    1.创建一个http.js ​ const baseUrl = 'http://192.168.1.188:8080'; const httpRequest = (opts, data) => ...

  9. 拨云见日,彻底弄清楚Java日志框架 log4j, logback, slf4j的区别与联系

    log4j 以及 logback, slf4j 官网 日志框架的困惑 作为一个正常的项目,是必须有日志框架的存在的,没有日志,很难追踪一些奇奇怪怪的系统问题. 但是,我们经常在项目的依赖中,见到奇奇怪 ...

  10. JVM(1) Java内存区域

    对于Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,不容易出现内存泄漏和内存溢出问题.不过,也正是因为Java程序员把内存控制的权 ...