用代码直接创建unity mesh 网格。
示例为可以不断拉长的曲形的面片。网格完成后会进行平滑插值,让曲形更加平滑。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshPlan : MonoBehaviour {
// Use this for initialization
//坐标顶点
private List<Vector3> OrignPos;
private MeshFilter meshFilter;
public Transform StartPlan;
public Transform EndPlan;
//重新绘制的间隔距离
public float Mid = 0.005f;
//
private List<Vector3> LeftPos;
private List<Vector3> RightPos;
public void Init()
{
//记录的初始位置赋值
CurrentPos_L = EndPlan.GetChild(0).position;
OldPos_L = CurrentPos_L;
CurrentPos_R = EndPlan.GetChild(1).position;
OldPos_R = CurrentPos_R;
meshFilter = GetComponent<MeshFilter>();
//初始化坐标顶点的集合
OrignPos = new List<Vector3>();
LeftPos = new List<Vector3>();
RightPos = new List<Vector3>();
for(int i = 0; i < 2; i++)
{
OrignPos.Add(StartPlan.GetChild(i).position);
// print(StartPlan.GetChild(i).position);
}
for(int i = 0; i < 2; i++)
{
OrignPos.Add(EndPlan.GetChild(i).position);
//print(EndPlan.GetChild(i).position);
}
GetLeftAndRightPos();
}
// Use this for initialization
void Start()
{
Init();
// EditorMesh();
}
//编辑
public void EditorMesh()
{
int count = OrignPos.Count;
int CubeNum = count / 2 - 1;
Vector3[] newVertices = new Vector3[count];
Vector3[] newNormals = new Vector3[count];
int[] newTriangles = new int[CubeNum * 4 * 3];
for(int i = 0; i < count; i++)
{
newVertices[i] = OrignPos[i];
}
#region 三角面构建
int currentCount = 0;
for(int i = 0; i < CubeNum; i = i + 1)
{
newTriangles[currentCount++] = i * 2;
newTriangles[currentCount++] = i * 2 + 2;
newTriangles[currentCount++] = i * 2 + 3;
newTriangles[currentCount++] = i * 2;
newTriangles[currentCount++] = i * 2 + 3;
newTriangles[currentCount++] = i * 2 + 1;
newTriangles[currentCount++] = i * 2 + 1;
newTriangles[currentCount++] = i * 2 + 3;
newTriangles[currentCount++] = i * 2 + 2;
newTriangles[currentCount++] = i * 2 + 1;
newTriangles[currentCount++] = i * 2 + 2;
newTriangles[currentCount++] = i * 2 + 0;
}
#endregion
//normal
for(int i = 0; i < count; i++)
{
newNormals[i] = new Vector3(0, 1, 0);
}
//UV
List<Vector2> NewUv = new List<Vector2>();
NewUv.Add(new Vector2(0, 0));
NewUv.Add(new Vector2(0, 1));
for(int i = 0; i < CubeNum; i++)
{
NewUv.Add(new Vector2(1, 1));
NewUv.Add(new Vector2(1, 0));
}
//创建网格
Mesh mesh = new Mesh();
meshFilter.mesh = mesh;
mesh.vertices = newVertices;
mesh.triangles = newTriangles;
mesh.uv = NewUv.ToArray();
mesh.normals = newNormals;
// mesh.RecalculateNormals();
}
void AddNewPoint()
{
for(int i = 0; i < 2; i++)
{
OrignPos.Add(EndPlan.GetChild(i).position);
}
}
//偏移位置
private Vector3 OldPos_L;
private Vector3 CurrentPos_L;
private Vector3 OldPos_R;
private Vector3 CurrentPos_R;
private void FixedUpdate()
{
CurrentPos_L = EndPlan.GetChild(0).position;
CurrentPos_R = EndPlan.GetChild(1).position;
if(Vector3.Distance(CurrentPos_L, OldPos_L) > Mid || Vector3.Distance(CurrentPos_R, OldPos_R) > Mid)
{
AddNewPoint();
EditorMesh();
}
OldPos_L = CurrentPos_L;
OldPos_R = CurrentPos_R;
}
private void GetLeftAndRightPos()
{
if(LeftPos.Count > 0)
{
LeftPos.Clear();
RightPos.Clear();
}
for(int i = 0; i < OrignPos.Count; i++)
{
if(i % 2 == 0)
{
LeftPos.Add(OrignPos[i]);
}
else
{
RightPos.Add(OrignPos[i]);
}
// print(OrignPos[i]);
}
}
private void GetAllPoint()
{
OrignPos.Clear();
int count = LeftPos.Count + RightPos.Count;
// print("coun="+ count);
for(int i = 0; i < count; i++)
{
if(i % 2 == 0)
{
OrignPos.Add(LeftPos[i/2]);
}
else
{
OrignPos.Add(RightPos[(i-1) / 2]);
}
}
// print("OrignPos=" + OrignPos.Count);
}
public void SetLerpVertices()
{
GetLeftAndRightPos();
List<Vector3> L = LeftPos;
List<Vector3> R = RightPos;
int span;
if(LeftPos.Count > 10)
span = 10;
else
span = 3;
LeftPos = SmoothPos.SmoothPoint(L, span);
RightPos = SmoothPos.SmoothPoint(R, span);
GetAllPoint();
EditorMesh();
}
public void CutLerpVertices()
{
GetLeftAndRightPos();
LeftPos = CutLerp(LeftPos);
RightPos = CutLerp(RightPos);
GetAllPoint();
EditorMesh();
}
//简化删值
private List<Vector3> CutLerp(List<Vector3> PosList)
{
Vector3 OldDirec;
Vector3 CurrentDirec;
List<Vector3> list = new List<Vector3>();
int count = PosList.Count;
if(count < 3)
return PosList;
OldDirec = PosList[1]-PosList[0];
CurrentDirec = OldDirec;
list.Add(PosList[0]);
for(int i = 1; i < count-1; i++)
{
CurrentDirec = PosList[i+1] - PosList[i];
if(Vector3.Angle(CurrentDirec, OldDirec) > 0.1f)
{
list.Add(PosList[i]);
}
OldDirec = CurrentDirec;
}
list.Add(PosList[count - 1]);
// print("S="+count+" N="+list.Count);
return list;
}
}
SmoothPos代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class SmoothPos : MonoBehaviour {
// Use this for initialization
void Start () {
}
public static List<Vector3> SmoothPoint(List<Vector3> list, int s)
{
List<Vector3> reslist = new List<Vector3>();
int Count = list.Count;
double[] x = new double[Count];
double[] y = new double[Count];
double[] z = new double[Count];
double[] X = new double[Count];
double[] Y = new double[Count];
double[] Z = new double[Count];
for(int i = 0; i < Count; i++)
{
x[i] = list[i].x;
y[i] = list[i].y;
z[i] = list[i].z;
}
X = MovingAverage(x, s);
Y = MovingAverage(y, s);
Z = MovingAverage(z, s);
for(int i = 0; i < Count; i++)
{
Vector3 V = new Vector3((float)X[i],(float)Y[i],(float)Z[i]);
reslist.Add(V);
}
return reslist;
}
public static double[] MovingAverage(double[] data, int span)
{
int b = 0;
if(span % 2 == 1)
b = (span - 1) / 2;
else
{
span -= 1;
b = (span - 1) / 2;
}
double[] smoothArray = new double[data.Length];
if(data.Length > span)
{
for(int i = 0; i < data.Length; i++)
{
if(i < b)
{
smoothArray[i] = 0;
for(int j = -i; j < i + 1; j++)
{
smoothArray[i] += data[i + j];
}
smoothArray[i] /= (2 * i + 1);
}
else if(i >= b && (data.Length - i) > b)
{
smoothArray[i] = 0;
for(int j = -b; j < b + 1; j++)
{
smoothArray[i] += data[i + j];
}
smoothArray[i] /= span;
}
else
{
smoothArray[i] = 0;
int c = data.Length - i - 1;
for(int j = -c; j < c + 1; j++)
{
smoothArray[i] += data[i + j];
}
smoothArray[i] /= (2 * c + 1);
}
}
}
else
{
throw new ArgumentException("span is bigger than data's count");
}
return smoothArray;
}
}