Unity에서 베지어 곡선을 그려보자.

안또니오·2023년 11월 14일
0

유니티

목록 보기
6/6
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class BezierCurve : Graphic
{
    public List<Vector3> vectors;
    [Range(0.5f, 500f)]
    public float thickness= 1f;
    private Vector3 initVec;
    private Vector3 unitVector;
    protected override void OnPopulateMesh(VertexHelper vh)
    {

        vh.Clear();
        initVec = Vector3.zero;
        var _thickness = thickness * 0.5f;
        unitVector = (Vector3.right * _thickness);

		// 첫 점을 0,0,0 으로 고정해주기 위함.
        if(vectors[0]!=Vector3.zero)
        {
            var tmp = new List<Vector3>();
            tmp.Add(Vector3.zero);
            tmp.AddRange(vectors);

            vectors = tmp;
        }
		// 각 포인트를 표시하기 위함.
        for (int i = 0; i < vectors.Count; i++)
        {
            DrawPoint(vh, vectors[i], i);
        }

        var bezier = DrawBezierCurve(vectors, 100);
        for(int i = 0; i< bezier.Count; i++)
        {
            DrawLine(vh, bezier[i], i + vectors.Count);
        }

    }

    void DrawLine(VertexHelper vh, Vector3 point, int index)
    {
        var vertex = UIVertex.simpleVert;

        vertex.color = color;
        // 여기서 90도를 더해줘야하는 이유는 모르겠다.
        var angle = GetAngle(initVec, point) + 90f;

        vertex.position = initVec;
        vertex.position -= Quaternion.Euler(0, 0, angle) * unitVector;
        vh.AddVert(vertex);

        vertex.position = initVec;
        vertex.position += Quaternion.Euler(0, 0, angle) * unitVector;
        vh.AddVert(vertex);

        vertex.position = point;
        vertex.position -= Quaternion.Euler(0, 0, angle) * unitVector;
        vh.AddVert(vertex);

        vertex.position = point;
        vertex.position += Quaternion.Euler(0, 0, angle) * unitVector;
        vh.AddVert(vertex);

        vh.AddTriangle(index * 4 + 0 , index * 4 + 1, index * 4 + 2);
        vh.AddTriangle(index * 4 + 2 , index * 4 + 3 , index * 4 + 1);

		// 칸과 칸을 매끈하게 만들기 위함.
        if(index > vectors.Count)
        {
            var idx = index - 1;
            vh.AddTriangle(idx * 4 + 2, idx * 4 + 3, index * 4 + 0);
            vh.AddTriangle(idx * 4 + 2, idx * 4 + 3, index * 4 + 1);
        }

        initVec = point;
    }

    void DrawPoint(VertexHelper vh, Vector3 point, int index)
    {
        var vertex = UIVertex.simpleVert;

        vertex.color = Color.white;

        var _45d = Mathf.Deg2Rad * 45f;
        var sin = 15 * Mathf.Sin(_45d) * 0.5f;
        var cos = 15 * Mathf.Cos(_45d) * 0.5f;

        vertex.position = point + new Vector3(cos, sin, 0);
        vh.AddVert(vertex);

        
        vertex.position = point + new Vector3(-cos, sin, 0);
        vh.AddVert(vertex);

        
        vertex.position = point + new Vector3(cos, -sin, 0);
        vh.AddVert(vertex);

        
        vertex.position = point + new Vector3(-cos, -sin, 0);
        vh.AddVert(vertex);

        vh.AddTriangle(index * 4 + 0, index * 4 + 1, index * 4 + 2);
        vh.AddTriangle(index * 4 + 2, index * 4 + 3, index * 4 + 1);

    }

    float GetAngle(Vector3 begin, Vector3 end)
    {
        return (float)(Mathf.Atan2(end.y - begin.y, end.x - begin.x) * (180 / Mathf.PI));
    }


    public List<Vector3> DrawBezierCurve(List<Vector3> points, int capacity)
    {
        var delta = 1f / capacity;
        float time = 0f;

        List<Vector3> returnList = new List<Vector3>();

        var p0 = points[0];
        var p1 = points[1];
        var p2 = points[2];

        for(int i = 0; i< capacity;i++)
        {
            var q0 = Vector3.Lerp(p0, p1, time);
            var q1 = Vector3.Lerp(p1, p2, time);

            var r0 = Vector3.Lerp(q0, q1, time);
            time += delta;

            returnList.Add(r0);
        }

        return returnList;
    }



}

이런점들을

이렇게

베지어 곡선을 그리기 위한 일반식을 위해서는 재귀함수를 이용해야 할 것 같은데, 아직은 거기까지는 좀......

profile
2020. 11월 공부시작.

1개의 댓글

comment-user-thumbnail
2023년 11월 14일

+90을 해줘야하는 이유는 알았다.
90을 해줘야 사각형이 그려진다.

답글 달기