반응형

어느날 지인에게 메쉬를 생성하는법을 알려달라고 연락이 왔다.

해본적은 없지만(메쉬 개념도 없었다...) 재미있을거같아서 한번 시도해보았다.

 

1. 메쉬 생성(vertices, uv) : vertices만 알면 되는거같아서 uv 설정은 하지 않음.

2. Raycast를 이용해서 vertices 값이 유동적으로 바뀔수 있어야한다.

3. Circle 형태여야 함.

 

연락받았을 당시, 어몽어스에서 그림자가 표현되는 것을 상상했다.

그래서 코드를 2D로 만들었다가, 나중에 3D로 만들어야 된다고 뒤늦게 들어서.. 안타깝게도 코드가 2D와 3D가 섞인 코드가 됐다.

 

※※ 메쉬에 대한 개념은 구글링하면 바로나오니 패스한다.


  • 코드
using UnityEngine;
using UnityEngine.Rendering;

public class MeshCreater : MonoBehaviour
{
    public Material meshMaterial;

    private Mesh mesh;
    private MeshFilter meshFilter;
    private MeshRenderer meshRender;

    private void Start()
    {
        GameObject meshGameObject = new GameObject("Mesh", typeof(MeshFilter), typeof(MeshRenderer));
        meshFilter = meshGameObject.GetComponent<MeshFilter>();
        meshRender = meshGameObject.GetComponent<MeshRenderer>();

        meshRender.material = meshMaterial;

        mesh = new Mesh();
        meshFilter.mesh = mesh;
    }

    private void Update()
    {
        CalculateMesh();
    }

    //Calculate vertex vector(circle)
    private Vector3 ConvertAngleToVector(float _angle)
    {
        var rad = _angle * Mathf.Deg2Rad;
        return new Vector3(Mathf.Cos(rad), Mathf.Sin(rad));
    }

    //*** Mesh vertices point : local position of gameObject
    //recalculate vertices for vertices of mesh
    private void CalculateMesh()
    {
        float targetAngle = 360f;
        int rayCount = 360;
        float angleIncrease = targetAngle / rayCount;
        float angle = 0f;
        float dist = 2f;
        
        //Arr Length : ray counts + cneter point
        Vector3[] vertices = new Vector3[rayCount + 1];
        //Triangles : Multiple of 3
        int[] triangles = new int[rayCount * 3];

        //Center point is always Vector3.zero
        Vector3 centerPoint = Vector3.zero;
        //Set the center point to vertices[0] (triangle index 0)
        vertices[0] = centerPoint;

        int vertexIndex = 1;
        int triangleIndex = 0;
        for (int i = 0; i < vertices.Length; i++)
        {
            if (vertexIndex < vertices.Length)
            {
                Vector3 vertex = ConvertAngleToVector(angle);
                RaycastHit hit;

                //Get vertex points
                if (Physics.Raycast(meshRender.transform.position, vertex, out hit, dist))
                {
                    //Recalculate mesh point(local position)
                    //Set the local position(vertices), after Subtract the meshRender position from hit point.
                    vertices[vertexIndex] = hit.point - meshRender.transform.position;
                }
                else
                {
                    vertices[vertexIndex] = vertex * dist;
                }
            }

            //Set triangles
            if (vertexIndex > 1)
            {
                triangles[triangleIndex] = 0;
                triangles[triangleIndex + 1] = vertexIndex - 1;
                triangles[triangleIndex + 2] = vertexIndex < vertices.Length ? vertexIndex : 1;

                triangleIndex += 3;
            }

            vertexIndex++;
            angle -= angleIncrease;
        }

        //Apply mesh info
        mesh.vertices = vertices;
        mesh.triangles = triangles;
    }
}

 

※※ ConvertAngleToVector(float)는 삼각비를 이용해서 각도로 좌표를 구하는 함수다. (Raycast 함수의 direction 값이라 거리값은 필요가 없음.)

※※ 위 함수가 이해가 안간다면 다음글 참고

링크 : [유니티] 삼각비를 이용해 각도로 좌표구하기

 

[유니티] 삼각비를 이용해 각도로 좌표구하기.

삼각비 삼각비는 직각 삼각형에서 각 A에 대해 세 변의 길이가 이루는비가 일정한걸 말한다. 위와 같은 삼각형에서 빗변(r), 대변(y), 이웃변(x)로 확인해보자. 여기서 각 A가 동일하면 다음과 같은

srdeveloper.tistory.com


  • 결과 보기

 

일단 개념을 잡는 쪽에 맞춰둔 코드라, 활용이나 최적화 작업은 목적에 따라 바뀔것 같다.

추가로 빛으로 활용하기 위한 참고 사이트 링크도 올려둠.

 

2d Visibility

The next step is to keep track of which walls the sweep ray passes through. Only the nearest wall is visible. How do you figure out which wall is nearest? The simplest thing is to calculate the distance from the center to the wall. However, this approach d

www.redblobgames.com

 

반응형

+ Recent posts