中目標-生成完整面
在之前的內容中我們已經成功生成了一個面,接下來我們要生成剩下的面就很容易了。
我們把之前生成的面當作頂面,接着我們來生成底面。
還記得前面說過\(\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;
}
}
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線
※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益
※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象
※南投搬家前需注意的眉眉角角,別等搬了再說!