유니티로 꼬불꼬불 곡선 그리기 2
0. 참조
메쉬 제작은 아래 링크를 참조했다.
곡선을 만들기 위해서는 여러가지 공식이 있는데 그 중에서도 가장 간단한 베지어 곡선을 사용했다.
1. 코드
MeshFilter meshFilter = CreateMesh;
public Mesh CreateMesh()
{
Mesh mesh = new Mesh();
mesh.Clear();
float scaling = 0.05f;
float width = DRMath.DenierToDiameter(yarn.thinkness, yarn.filaments);
List<Vector3> vertList = new List<Vector3>();
List<int> triList = new List<int>();
List<Vector2> uvList = new List<Vector2>();
Vector3 upNormal = new Vector3(0, 0, -1);
triList.AddRange(new int[] {
2, 1, 0, //start face
0, 3, 2
});
for (int s = 0; s < numPoints; s++)
{
float t = ((float)s) / numPoints;
float futureT = ((float)s + 1) / numPoints;
Vector3 segmentStart = DRMath.CalculateCubicBezierPoint(t, lerpPosition[0], lerpPosition[1], lerpPosition[2], lerpPosition[3]);
Vector3 segmentEnd = DRMath.CalculateCubicBezierPoint(futureT, lerpPosition[0], lerpPosition[1], lerpPosition[2], lerpPosition[3]);
Vector3 segmentDirection = segmentEnd - segmentStart;
//Debug.Log(segmentDirection);
if (s == 0 || s == numPoints - 1)
segmentDirection = new Vector3(0, 1, 0);
segmentDirection.Normalize();
Vector3 segmentRight = Vector3.Cross(upNormal, segmentDirection);
segmentRight *= width;
Vector3 offset = segmentRight.normalized * (width / 2) * scaling;
Vector3 br = segmentRight + upNormal * width + offset;
Vector3 tr = segmentRight + upNormal * -width + offset;
Vector3 bl = -segmentRight + upNormal * width + offset;
Vector3 tl = -segmentRight + upNormal * -width + offset;
int curTriIdx = vertList.Count;
Vector3[] segmentVerts = new Vector3[]
{
segmentStart + br,
segmentStart + bl,
segmentStart + tl,
segmentStart + tr,
};
vertList.AddRange(segmentVerts);
Vector2[] uvs = new Vector2[]
{
new Vector2(0, 0),
new Vector2(0, 1),
new Vector2(1, 1),
new Vector2(1, 1)
};
uvList.AddRange(uvs);
int[] segmentTriangles = new int[]
{
curTriIdx + 6, curTriIdx + 5, curTriIdx + 1, //left face
curTriIdx + 1, curTriIdx + 2, curTriIdx + 6,
curTriIdx + 7, curTriIdx + 3, curTriIdx + 0, //right face
curTriIdx + 0, curTriIdx + 4, curTriIdx + 7,
curTriIdx + 1, curTriIdx + 5, curTriIdx + 4, //top face
curTriIdx + 4, curTriIdx + 0, curTriIdx + 1,
curTriIdx + 3, curTriIdx + 7, curTriIdx + 6, //bottom face
curTriIdx + 6, curTriIdx + 2, curTriIdx + 3
};
triList.AddRange(segmentTriangles);
// final segment fenceposting: finish segment and add end face
if (s == numPoints - 1)
{
curTriIdx = vertList.Count;
vertList.AddRange(new Vector3[] {
segmentEnd + br,
segmentEnd + bl,
segmentEnd + tl,
segmentEnd + tr
});
uvList.AddRange(new Vector2[] {
new Vector2(0, 0),
new Vector2(0, 1),
new Vector2(1, 1),
new Vector2(1, 1)
}
);
triList.AddRange(new int[] {
curTriIdx + 0, curTriIdx + 1, curTriIdx + 2, //end face
curTriIdx + 2, curTriIdx + 3, curTriIdx + 0
});
}
}
mesh.vertices = vertList.ToArray();
mesh.triangles = triList.ToArray();
mesh.uv = uvList.ToArray();
mesh.RecalculateNormals();
mesh.RecalculateBounds();
return mesh;
}
※ DRMath.CalculateCubicBezierPoint는 베지어 그리기 포스팅에 있으니 참조하면 된다.
이 리턴 값을 MeshFilter에다가 넣어주면 만들어진 메쉬가 보여질 것이다.
2. 스크린샷
해당 코드를 이용해 만든 결과물이다.