odyssey

#5 odyssey 개발일지 : 베지어 곡선으로 곡선 지형 생성

san10 2023. 3. 17. 00:08

지금까지는 임시로 곡선 지형을 만들었는데

이제는 베지어 곡선으로 지형을 만들려고 한다.

 

베지어 곡선이란?

n개의 조절점과 선형 보간을 통해 얻을 수 있는 곡선으로, n-1차 베지어 곡선이라고 부른다.

 

3차 베지어 곡선을 그린다고 할때, 각 조절점을 A, B, C라고 가정하면

선분 AB, 선분 BC를 그릴 수 있다.

선분 AB와 BC 사이에서, 0~1사이의 값 t 만큼 비례한 점인 D, E를 찾는다.

여기서는 t=0.1이라고 가정

선분 DE에서도 위에서 했던 것처럼 t값 만큼 비례한 점인 F를 찾고, 

t가 0~1까지 변화할때, F가 그리는 궤적이 2차 베지어 곡선이다.

 

 

 

코드로 구현

유니티에서 Vector3.Lerp()라는 함수를 통해 쉽게 구현할 수 있었다!

public class BezierGenerator : MonoBehaviour
{
    public Vector3 p1;
    public Vector3 p2;
    public Vector3 p3;
    public Vector3 p4;
    public GameObject pointOBJ;

    public List<Vector3> BezierList = new List<Vector3>();

    private Vector3 BezierPoint(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, float t)
    {
        Vector3 A = Vector3.Lerp(p1, p2, t);
        Vector3 B = Vector3.Lerp(p2, p3, t);
        Vector3 C = Vector3.Lerp(p3, p4, t);

        Vector3 D = Vector3.Lerp(A, B, t);
        Vector3 E = Vector3.Lerp(B, C, t);

        Vector3 F = Vector3.Lerp(D, E, t);
        return F;
    }

    private void GenerateBezierList(int pointNum)
    {
        float interval = (float)1 / pointNum;

        for(int i = 0; i < pointNum; i++)
        {
            Vector3 point=BezierPoint(p1, p2, p3, p4, interval*i);
            BezierList.Add(point);
            Instantiate(pointOBJ, point, Quaternion.identity);
        }
    }
}

위 코드는 3차 베지어 곡선을 그리는 코드이다..

 

https://blog.naver.com/PostView.nhn?blogId=dasoong15&logNo=222223767429&parentCategoryNo=&categoryNo=7&viewDate=&isShowPopularPosts=true&from=search 

 

유니티 베지어 곡선 구현방법

https://www.youtube.com/watch?v=KTEX2L4T4zE 아래는 4개의 점 이상의 베지어 곡선 구현입니...

blog.naver.com

이 블로그의 코드를 참고해서 만들었다.

 

이렇게 원하는 대로 베지어 곡선이 생성된 것을 볼 수 있다...

 

 

저번에 만들어놓았던 GeneratorMesh를 통해 베지어 곡선의 점들을 바탕으로 메쉬를 생성하고, 

머테리올도 붙였다.

최종적으로 이렇게 생긴 지형이 생성되었다!

public class BezierMeshGenerator : MonoBehaviour
{
    public BezierGenerator bezierGenerator;
    public GeneratorMesh generatorMesh;
    public List<Vector3> bezierPointList;

    public Vector3 p1; //테스트용
    public Vector3 p2;
    public Vector3 p3;
    public Vector3 p4;
    public int pointNum;

    public void CreateBezierMesh(
        Vector3 p1,
        Vector3 p2,
        Vector3 p3,
        Vector3 p4,
        int pointNum
        )
    {
        GameObject ground = new GameObject();
        PolygonCollider2D polygonCollider2D= new PolygonCollider2D();
        
        Vector2[] bezierPoints = bezierGenerator.GenerateBezierList(p1, p2, p3, p4,pointNum);
        polygonCollider2D= ground.AddComponent<PolygonCollider2D>();
        polygonCollider2D.points = bezierPoints;

        generatorMesh.generateMesh(ground);
    }

    public void test()
    {
        CreateBezierMesh(p1, p2, p3, p4,pointNum);
    }
}