본문 바로가기
개발/Unity

유니티 - 절차적 메시로 정다각기둥, 원기둥 그리기 개선 (Make Regular Prism, Cylinder with Procedural Mesh 2)

by 피로물든딸기 2022. 11. 6.
반응형

Unity 전체 링크

 

절차적 메시로 정다각기둥, 원기둥 그리기에서 정점의 개수를 줄여보자.

 

ProceduralRegularPrismUpgrade.cs를 추가하고 ProceduralRegularPrism.cs를 복사한 후 코드를 수정한다.

옆면 생성 코드를 개선하면 된다.

 

밑면의 정점을 먼저 만들고 윗면의 정점을 추가한다.

그리고 해당 정점 2 * N개만 triangles에 배치한다. (이전 코드는 4 * N개였다.)

    /* -------------------- 옆면 + 개선 -------------------- */

    vIdx = 2 * polygon + 2;
    for (int i = 1; i <= polygon; i++)
    {
        float angle = -i * (Mathf.PI * 2.0f) / polygon;

        vertices[vIdx++]
            = new Vector3(Mathf.Cos(angle) * size, -height / 2.0f, Mathf.Sin(angle) * size) + offset;
    }

    for (int i = 1; i <= polygon; i++)
    {
        float angle = -i * (Mathf.PI * 2.0f) / polygon;

        vertices[vIdx++]
            = new Vector3(Mathf.Cos(angle) * size, height / 2.0f, Mathf.Sin(angle) * size) + offset;
    }

    tIdx = 6 * polygon;
    for (int i = 0; i < polygon - 1; i++)
    {
        triangles[tIdx++]= (2 * polygon + 2) + i + 0;
        triangles[tIdx++]= (2 * polygon + 2) + i + 1;
        triangles[tIdx++]= (2 * polygon + 2) + i + polygon;
                                               
        triangles[tIdx++]= (2 * polygon + 2) + i + 1;
        triangles[tIdx++]= (2 * polygon + 2) + i + 1 + polygon;
        triangles[tIdx++]= (2 * polygon + 2) + i + polygon;
    }

    triangles[tIdx++] = (2 * polygon + 2) + polygon - 1;
    triangles[tIdx++] = (2 * polygon + 2) + 0;
    triangles[tIdx++] = (2 * polygon + 2) + polygon - 1 + polygon;
                                            
    triangles[tIdx++] = (2 * polygon + 2) + 0;
    triangles[tIdx++] = (2 * polygon + 2) + polygon;
    triangles[tIdx++] = (2 * polygon + 2) + polygon - 1 + polygon;

 

개선된 코드로 게임을 실행해보자. (왼쪽이 Upgrade ver)

N이 작은 경우 정점이 부족하여 라이팅 연산이 제대로 되지 않는다.

wireframe 추가

 

하지만 N이 적절히 크다면 정점이 정보를 잘 공유하여 라이팅 연산을 잘 하게 된다.

즉, N이 클수록 옆면이 연속으로 붙어있게 되므로 정점을 줄이는 것이 성능 향상에 도움이 된다.

또한 정점이 적은 쪽이 더 부드럽다.

wireframe 추가

 

처음에는 정점이 부족해서 라이팅 연산이 잘 안되지만, N이 커질수록 큰 문제가 없다.

 

이전 정다각기둥개선된 정다각기둥을 비교해보자.

원기둥에 가까워질수록 두 오브젝트는 큰 차이가 없다.

 

따라서 N이 큰 경우라면 정점이 적은 것이 성능에 도움이 된다.

 

전체 코드는 다음과 같다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class ProceduralRegularPrismUpgrade : MonoBehaviour
{
    public int polygon = 3;
    public float size = 1.0f;
    public float height = 1.0f;
    public Vector3 offset = new Vector3(0, 0, 0);

    Mesh mesh;
    Vector3[] vertices;
    int[] triangles;

    public void makePolygon(int polygon)
    {
        setMeshData(size, polygon);
        createProceduralMesh();
    }

    void OnValidate()
    {
        if (mesh == null) return;

        if (size > 0 || offset.magnitude > 0 || polygon >= 3 || height > 0)
        {
            setMeshData(size, polygon);
            createProceduralMesh();
        }
    }

    void Start()
    {
        mesh = GetComponent<MeshFilter>().mesh;

        setMeshData(size, polygon);
        createProceduralMesh();
    }

    void setMeshData(float size, int polygon)
    {
        /* -------------------- 밑면 -------------------- */

        vertices = new Vector3[(polygon + 1) + (polygon + 1) + (polygon * 4)];

        vertices[0] = new Vector3(0, -height / 2.0f, 0) + offset;
        for (int i = 1; i <= polygon; i++)
        {
            float angle = -i * (Mathf.PI * 2.0f) / polygon;

            vertices[i]
                = new Vector3(Mathf.Cos(angle) * size, -height / 2.0f, Mathf.Sin(angle) * size) + offset;
        }

        triangles = new int[(3 * polygon) + (3 * polygon) + (6 * polygon)];
        for (int i = 0; i < polygon - 1; i++)
        {
            triangles[i * 3] = 0;
            triangles[i * 3 + 1] = i + 2;
            triangles[i * 3 + 2] = i + 1;
        }

        triangles[3 * polygon - 3] = 0;
        triangles[3 * polygon - 2] = 1;
        triangles[3 * polygon - 1] = polygon;

        /* -------------------- 윗면 -------------------- */

        int vIdx = polygon + 1;
        vertices[vIdx++] = new Vector3(0, height / 2.0f, 0) + offset;
        for (int i = 1; i <= polygon; i++)
        {
            float angle = -i * (Mathf.PI * 2.0f) / polygon;

            vertices[vIdx++]
                = new Vector3(Mathf.Cos(angle) * size, height / 2.0f, Mathf.Sin(angle) * size) + offset;
        }

        int tIdx = 3 * polygon;
        for (int i = 0; i < polygon - 1; i++)
        {
            triangles[tIdx++] = polygon + 1;
            triangles[tIdx++] = i + 1 + polygon + 1;
            triangles[tIdx++] = i + 2 + polygon + 1;
        }

        triangles[tIdx++] = polygon + 1;
        triangles[tIdx++] = polygon + polygon + 1;
        triangles[tIdx++] = 1 + polygon + 1;

        /* -------------------- 옆면 + 개선 -------------------- */

        vIdx = 2 * polygon + 2;
        for (int i = 1; i <= polygon; i++)
        {
            float angle = -i * (Mathf.PI * 2.0f) / polygon;

            vertices[vIdx++]
                = new Vector3(Mathf.Cos(angle) * size, -height / 2.0f, Mathf.Sin(angle) * size) + offset;
        }

        for (int i = 1; i <= polygon; i++)
        {
            float angle = -i * (Mathf.PI * 2.0f) / polygon;

            vertices[vIdx++]
                = new Vector3(Mathf.Cos(angle) * size, height / 2.0f, Mathf.Sin(angle) * size) + offset;
        }

        tIdx = 6 * polygon;
        for (int i = 0; i < polygon - 1; i++)
        {
            triangles[tIdx++]= (2 * polygon + 2) + i + 0;
            triangles[tIdx++]= (2 * polygon + 2) + i + 1;
            triangles[tIdx++]= (2 * polygon + 2) + i + polygon;
                                               
            triangles[tIdx++]= (2 * polygon + 2) + i + 1;
            triangles[tIdx++]= (2 * polygon + 2) + i + 1 + polygon;
            triangles[tIdx++]= (2 * polygon + 2) + i + polygon;
        }

        triangles[tIdx++] = (2 * polygon + 2) + polygon - 1;
        triangles[tIdx++] = (2 * polygon + 2) + 0;
        triangles[tIdx++] = (2 * polygon + 2) + polygon - 1 + polygon;
                                            
        triangles[tIdx++] = (2 * polygon + 2) + 0;
        triangles[tIdx++] = (2 * polygon + 2) + polygon;
        triangles[tIdx++] = (2 * polygon + 2) + polygon - 1 + polygon;

        Debug.Log("Upgrade : " + vIdx + "  " + tIdx);
    }

    void createProceduralMesh()
    {
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();

        Destroy(this.GetComponent<MeshCollider>());
        this.gameObject.AddComponent<MeshCollider>();
    }
}

 

참고 - PolygonController.cs를 빈 오브젝트에 추가하여 동시에 N 값을 변경하였다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PolygonController : MonoBehaviour
{
    public GameObject pol1, pol2;
    public int polygon;

    ProceduralRegularPrism prp;
    ProceduralRegularPrismUpgrade prpu;

    void OnValidate()
    {
        if (prp == null) return;

        if (polygon >= 3)
        {
            prp.makePolygon(polygon);
            prpu.makePolygon(polygon);
        }
    }

    void Start()
    {
        prp = pol1.GetComponent<ProceduralRegularPrism>();
        prpu = pol2.GetComponent<ProceduralRegularPrismUpgrade>();
    }
}

 

각 스크립트에는 아래 함수를 추가하였다.

    public void makePolygon(int polygon)
    {
        setMeshData(size, polygon);
        createProceduralMesh();
    }

 

위의 실행결과는 아래의 unitypackage에서 확인 가능하다.

CompareProceduralPrism.unitypackage
0.00MB

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글