(不重要的前言:该博文为系列博文,每一篇有前后文关系,例如基类、组件的集成,如果发现有陌生组件和基类,请查看前面文章,本系列文章单纯应用unity的mesh来绘制模型,并未使用任何三方插件,文章内容、代码都是纯手打,望支持)
一个管道有四个面,分别是顶面、地面、内侧面、外侧面,先看顶面:
这其实就是一个铰链,内边和外边的顶点个数是一样的,头尾重合,就能画出一个圆圈。
其他部位:
外圈为circle1,内圈为circle2
circle1和circle2组合成顶面,circle1和circle2向下偏移一个高度circle3和circle4,组合成底面,
circle1和circle3组成外侧面,circle2和circle4组层内侧面
四个面就是四个铰链,用多边形组合也能画,但是顶点会更多,用铰链组件更加合适。
上代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MeshMaker.Utility;
using UnityEditor;
namespace MeshMaker.Maker
{
/// <summary>
/// 管子
/// radius = 半径
/// height = 高度
/// density = 密度(密度越高,边缘越圆润)
/// thickness = 管壁厚度
/// </summary>
public class PipeMesh : BaseMesh
{
[CustomEditor(typeof(PipeMesh))]
public class Attribute : Editor {
public override void OnInspectorGUI()
{
PipeMesh mesh = target as PipeMesh;
mesh.radius = EditorGUILayout.Slider("radius", mesh.radius, 0.1f, 5);
mesh.height = EditorGUILayout.Slider("height", mesh.height, 0.1f, 5);
mesh.density = EditorGUILayout.IntSlider("density", mesh.density,3,50);
mesh.thickness = EditorGUILayout.Slider("thickness", mesh.thickness,0.1f,0.9f);
if (GUILayout.Button("Create")) mesh.Create();
}
}
public float radius = 1;
public float height = 1;
public int density = 4;
public float thickness = 0.1f;
private List<Vector3> positions;
public override void Create() {
Init();
ClearChilds();
CreateChain0();
CreateChain1();
CreateChain2();
CreateChain3();
}
private void Init() {
positions = new List<Vector3>();
float d = 360f / density;
for (int i = 0; i < density; i++)
{
Vector2 v = CircleUtility.GetPosByAngle(radius,d * i);
positions.Add(new Vector3(v.x, 0, v.y));
}
}
private void CreateChain0() {
List<Vector3> vectors = new List<Vector3>();
for (int i = 0; i < positions.Count; i++)
{
Vector3 v = positions[i];
Vector3 dir = (Vector3.zero - v) * thickness;
vectors.Add(GetPos(positions, i, false));
vectors.Add(GetPos(positions, i, true));
}
CreateChain(vectors, true, false);
}
private void CreateChain1()
{
List<Vector3> vectors = new List<Vector3>();
for (int i = 0; i < positions.Count; i++)
{
Vector3 v = positions[i];
Vector3 dir = (Vector3.zero - v) * thickness;
vectors.Add(GetPos(positions, i, false) + Vector3.up * height);
vectors.Add(GetPos(positions, i, true) + Vector3.up * height);
}
CreateChain(vectors, true, true);
}
private void CreateChain2()
{
List<Vector3> vectors = new List<Vector3>();
for (int i = 0; i < positions.Count; i++)
{
Vector3 v = positions[i];
Vector3 dir = (Vector3.zero - v) * thickness;
vectors.Add(GetPos(positions, i, false));
vectors.Add(GetPos(positions, i, false) + Vector3.up * height);
}
CreateChain(vectors, true, true);
}
private void CreateChain3()
{
List<Vector3> vectors = new List<Vector3>();
for (int i = 0; i < positions.Count; i++)
{
Vector3 v = positions[i];
Vector3 dir = (Vector3.zero - v) * thickness;
vectors.Add(GetPos(positions, i, true));
vectors.Add(GetPos(positions, i, true) + Vector3.up * height);
}
CreateChain(vectors, true, false);
}
private Vector3 GetPos(List<Vector3> positions,int index,bool move) {
Vector3 v = positions[index];
if (move)
{
Vector3 dir = (Vector3.zero - v) * thickness;
return v + dir;
}
else
{
return v;
}
}
}
}
public static Vector2 GetPosByAngle(float radius, float angle)
{
float x = 0;
float y = 0;
if (angle <= 90)
{
float a = angle;
float radian = a * Mathf.PI / 180;
x = radius * Mathf.Sin(radian);
y = Mathf.Sqrt(radius * radius - x * x);
}
else if (angle <= 180)
{
float a = 180 - angle;
float radian = a * Mathf.PI / 180;
x = radius * Mathf.Sin(radian);
y = -Mathf.Sqrt(radius * radius - x * x);
}
else if (angle <= 270)
{
float a = angle - 180;
float radian = a * Mathf.PI / 180;
x = -radius * Mathf.Sin(radian);
y = -Mathf.Sqrt(radius * radius - x * x);
}
else
{
float a = 360 - angle;
float radian = a * Mathf.PI / 180;
x = -radius * Mathf.Sin(radian);
y = Mathf.Sqrt(radius * radius - x * x);
}
return new Vector2(x, y);
}