베지어 곡선

김치헌·2024년 3월 7일
0

TIL

목록 보기
32/38

최종프로젝트를 대비하여 카메라 이동관련 코드를 정리하고자 한다.

베지어 곡선

컴퓨터 그래픽에서 임의의 형태의 곡선을 표현하기 위해 수학적으로 만든 곡선. 최초의 제어점(control point)인 시작점과 최후의 제어점인 끝점 그리고 그 사이에 위치하는 내부 제어점의 이동에 의해 다양한 자유 곡선을 얻는 방법이다. 이 때 곡선은 제어점 위를 통과하는 것은 아니다
[네이버 지식백과] 베지어 곡선 [bezier curve] (한글글꼴용어사전, 2000. 12. 25., 세종대왕기념사업회)

베지어 곡선을 통해 정확한 위치값이 필요하지 않은 스킬 등에 역동감을 불어 넣어주고자 한다.

카메라의 회전값도 위치에 따라 달라지겠지만 저번 팀과제에서 내적외적을 사용하여 계산을 해봤으니 어떻게든 되지 않을까? 물론 위치값도 내적 외적으로 현재 카메라의 위치를 확인하여 원하는 진행방향으로 각도를 더할 수 있지만 베지어 곡선이 더 편해보여 정확한 위치가 필요한 경우가 아니라면 전자를 사용해 보고자 한다.

필요한 매개변수

  1. 출발점
  2. 제어점(여러개 추가 할 수있음)
  3. 도착점

베지어 곡선 원리

  1. 출발점과 제어점을 연결하는 벡터를 러프1
  2. 제어점과 도착점을 연결하는 벡터를 러프2
  3. 두개의 러프를 러프시킴!

간단한 시각화를 위해 아래와 같이 구성하여 시간이 지속시간이 5초 각 1초마다 위치를 포인트로 표시하였다. 해당 포인트 번호를 0~4번으로 나타낸다면 0초일때 러프1과 러프2를 러프시키면 러프1과 동일한 벡터가 나온다. 1초뒤 러프1과 러브2는 1번 위치에 위치하고 두개를 러프시키게되면 1번 위치를 연결한 벡터로 이동한다. 같은 방법으로 4번까지 진행하면 물체는 빨간색 곡선을 그리며 이동하게 된다.

using UnityEngine;

public class BezierCurveWithTransforms : MonoBehaviour
{
    public Transform startPoint; // 시작점
    public Transform controlPoint; // 제어점
    public Transform endPoint; // 끝점

    public float duration = 3f; // 전체 이동 시간

    private float t = 0f; // 시간

    void Update()
    {
        // 시간 업데이트
        t += Time.deltaTime / duration;

        // 베지어 곡선 계산
        Vector3 position = CalculateBezierPoint(startPoint.position, controlPoint.position, endPoint.position, t);

        // 물체 이동
        transform.position = position;

        // t 값이 1보다 크면 초기화
        if (t > 1f)
            t = 0f;
    }

    // 베지어 곡선 계산
    Vector3 CalculateBezierPoint(Vector3 p0, Vector3 p1, Vector3 p2, float t)
    {
        // 세 개의 점에 대한 Lerp 계산
        Vector3 lerp1 = Vector3.Lerp(p0, p1, t);
        Vector3 lerp2 = Vector3.Lerp(p1, p2, t);

        // Lerp로 계산된 두 점에 대한 다시 Lerp 계산
        return Vector3.Lerp(lerp1, lerp2, t);
    }

    // 에디터 상에서 점들을 시각화
    void OnDrawGizmos()
    {
        if (startPoint != null && controlPoint != null && endPoint != null)
        {
            Gizmos.color = Color.red;
            Gizmos.DrawSphere(startPoint.position, 0.1f);
            Gizmos.DrawSphere(controlPoint.position, 0.1f);
            Gizmos.DrawSphere(endPoint.position, 0.1f);

            Gizmos.color = Color.white;
            Gizmos.DrawLine(startPoint.position, controlPoint.position);
            Gizmos.DrawLine(controlPoint.position, endPoint.position);
        }
    }
}
profile
초보개발자

0개의 댓글