참고 - 정다각기둥, 원기둥 만들기
절차적 메시를 이용하여 정다각형, 원을 만들었으니 정다각뿔, 정N각뿔을 만들어보자.
정사면체를 만드는 방법에서 높이를 조절할 수 있도록 변경하고 코드를 확장하면 된다.
먼저 정다각형의 triangles 코드의 순서를 아래와 같이 바꾼다.
삼각형이 N개 더 추가되므로 triangles의 크기가 3 * N개 추가된다.
시계 방향으로 생성한 mesh를 반시계 방향으로 만들어 아래에서 보이도록 한다.
triangles = new int[3 * polygon + 3 * 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;
높이도 조절하도록 추가한다.
참고로 높이의 절반이 오브젝트의 기준점이 된다.
public float height = 1.0f;
void OnValidate()
{
if (mesh == null) return;
if (size > 0 || offset.magnitude > 0 || polygon >= 3 || height > 0)
{
setMeshData(size, polygon);
createProceduralMesh();
}
}
높이를 정하는 꼭지점이 하나 추가되면서 삼각형이 N개 더 추가되므로 3 * N개의 정점을 추가한다.
그리고 높이의 중심이 기준이 되도록 y값도 수정한다.
vertices = new Vector3[polygon + 1 + (3 * polygon)];
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), -height / 2.0f, Mathf.Sin(angle)) * size) + offset;
}
그리고 y 좌표는 size에 영향을 받으면 안되므로, size를 x, z 축에만 곱하도록 수정한다.
vertices[i]
= (new Vector3(Mathf.Cos(angle) * size, -height / 2.0f, Mathf.Sin(angle) * size ) ) + offset;
밑면의 정다각형 외에 나머지 삼각형은 vertices 순서 그대로 triangles에 넣어주면 편하다.
정N각형을 만들면서 triangles의 index가 3 * N - 1이 되었으므로 tIdx를 3 * N부터 시작하면서 값을 넣는다.
int tIdx = 3 * polygon;
Vector3 point = new Vector3(0, height / 2.0f, 0) + offset;
for (int i = 1; i <= polygon - 1; i++)
{
vertices[polygon + 1 + 3 * i - 3] = point;
vertices[polygon + 1 + 3 * i - 2] = vertices[i];
vertices[polygon + 1 + 3 * i - 1] = vertices[i + 1];
triangles[tIdx++] = polygon + 1 + 3 * i - 3;
triangles[tIdx++] = polygon + 1 + 3 * i - 2;
triangles[tIdx++] = polygon + 1 + 3 * i - 1;
}
vertices[polygon + 1 + (3 * polygon) - 1 - 2] = point;
vertices[polygon + 1 + (3 * polygon) - 1 - 1] = vertices[polygon];
vertices[polygon + 1 + (3 * polygon) - 1 - 0] = vertices[1];
triangles[tIdx++] = polygon + 1 + (3 * polygon) - 1 - 2;
triangles[tIdx++] = polygon + 1 + (3 * polygon) - 1 - 1;
triangles[tIdx++] = polygon + 1 + (3 * polygon) - 1 - 0;
게임을 실행하고 설정을 변경하면 정다각뿔 → 원뿔을 만들어볼 수 있다.
Mesh Renderer를 끄면 아래와 같이 Mesh가 만들어지는 것을 볼 수 있다.
전체 코드는 다음과 같다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class ProceduralRegularPyramids : 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;
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 + (3 * polygon)];
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];
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 tIdx = 3 * polygon;
Vector3 point = new Vector3(0, height / 2.0f, 0) + offset;
for (int i = 1; i <= polygon - 1; i++)
{
vertices[polygon + 1 + 3 * i - 3] = point;
vertices[polygon + 1 + 3 * i - 2] = vertices[i];
vertices[polygon + 1 + 3 * i - 1] = vertices[i + 1];
triangles[tIdx++] = polygon + 1 + 3 * i - 3;
triangles[tIdx++] = polygon + 1 + 3 * i - 2;
triangles[tIdx++] = polygon + 1 + 3 * i - 1;
}
vertices[polygon + 1 + (3 * polygon) - 1 - 2] = point;
vertices[polygon + 1 + (3 * polygon) - 1 - 1] = vertices[polygon];
vertices[polygon + 1 + (3 * polygon) - 1 - 0] = vertices[1];
triangles[tIdx++] = polygon + 1 + (3 * polygon) - 1 - 2;
triangles[tIdx++] = polygon + 1 + (3 * polygon) - 1 - 1;
triangles[tIdx++] = polygon + 1 + (3 * polygon) - 1 - 0;
}
void createProceduralMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
Destroy(this.GetComponent<MeshCollider>());
this.gameObject.AddComponent<MeshCollider>();
}
}
참고
- 위의 경우 polygon이 많을 때 불필요한 정점이 상대적으로 많아진다.
- 따라서 정점을 필요한 만큼만 만들고 triangles로 배치한다.
Unity Plus:
Unity Pro:
Unity 프리미엄 학습:
댓글