본문 바로가기
programming | development/unity

Bezier Curve 이용해서 VR 텔레포트 ray 만들기

by foooo828 2021. 11. 1.

1. BezierCurve 

수식 거부감들어서 색블록으로 바꿈

 

 

 

1.1 Linear

  Vector3 CalculateLinearBezier(Vector3 p0, Vector3 p1, float t)
    {
        return (1 - t) * p0 + t * p1;
    }

 

 

1.2 Quadratic

 Vector3 CalculateQuadraticBezier(Vector3 p0, Vector3 p1, Vector3 p2, float t)
    {
        return (1 - t) * (1 - t) * p0 + 2 * t * p1 * (1 - t) + t * t * p2;
    }

 

   private void DrawLinearCurve()
    {
        for (int i = 1; i < point + 1; i++)
        {
            float t = i / (float) point;
            positions[i - 1] = CalculateLinearBezier(point0.position, point1.position, t);
        }

        line.SetPositions(positions);
    }

 

 

2. 텔레포트 곡선 만들기

 

텔레포트가 가능한 거리 영역이 정해져있을 때  두가지 경우를 생각해볼 수 있다. 

 

- 컨트롤러에서 컨트롤러 오브젝트의 forward 방향으로 ray 를 쐈을때 타겟이 없는경우

ray 를 쐈을때 타겟이 있는경우

 

 타겟이 없는 경우

 

 

컨트롤러의 위치를  P0 로 설정

끝지점에서 땅 방향으로 다시 ray 를 쏴서 부딪힌 지점을 타겟지점  P2  로 설정한다.

 

 

 

 

 

   P1 이 제한거리 끝에 위치할경우와 중간에 위치할 경우의 곡선차이 . 중간에 위치한게 개인적으로 더 자연스럽다.

 

 

 

 

  타겟이 있는 경우

 

 

 

컨트롤러의 위치를  P0  으로 놓고 타겟지점을  P2  로 둔다. 

그리고 곡선의 기준이 되는 지점을  P1 으로 설정한다.

 

 

 

 

 

 

 

 

제한거리 이내 텔리포트 타겟 지점이 있을경우 직선에 가까운 약간의 곡선을 넣었음

손과 타겟지점의 distance 비율에 따라 point1 의 높이를 다르게함

가까울수록 직선에 가깝고 멀수록 곡선이 생긴다.

 

 

 

 

   void Teleport()
    {
        RaycastHit hitInfo;
        float distanProportion = 0;
        float height;
        int layerFloor = 1 << LayerMask.NameToLayer("Floor");
        Vector3 thisPosition = transform.position;       

        if (Physics.Raycast(thisPosition, transform.forward, out hitInfo, teleportMaxDistance, layerFloor))
        {
            // 제한거리 이내 있을때
            distanProportion = hitInfo.distance / teleportMaxDistance;
            height = thisPosition.y - hitInfo.point.y;
            point0 = thisPosition;
            point1 = hitInfo.point + Vector3.up * height;
            point1.y = distanProportion * height;
            Vector3 p1Cache = point1;
            point1 = (point0 + p1Cache) * 0.5f;
            point2 = hitInfo.point;
        }
        else
        {
            // 제한거리 이내 없을때 
            Vector3 endPoint = transform.position + transform.forward * teleportMaxDistance;
          
            if (Physics.Raycast(endPoint, Vector3.down, out hitInfo, Mathf.Infinity, layerFloor))
            {
                point0 = thisPosition;
                point1 = endPoint;
                point1 = (point0 + point1) * 0.5f;
                point2 = hitInfo.point;
            }
            else
            {
            }
        }

 

 

 

참고 : https://www.youtube.com/watch?v=wgCxcOXMGgA http://www.theappguruz.com/blog/bezier-curve-in-games

http://www.theappguruz.com/blog/bezier-curve-in-games

https://www.youtube.com/watch?v=pnYccz1Ha34

 

 

 

 

댓글