Mesh를 통해 다양한 모양의 면적, 부피를 계산하는 법.
1. 설명
- Mesh는 vertices의 점과, 해당 점을 이은 triangles 를 통해 폴리곤을 만들고, 이를 화면에 표현하여 3D로 보여준다.
- 즉, 3각형의 면적들을 모두 더한다면, 전체 면적을 알 수 있고, 부피의 경우 높이값이 별도로 필요하다.
- 단, 경우에 따라 triangles 에 있으나 삼각형이 아닌 값들, 중복된 값들, 대각선의 삼각형 등은 제외해야 한다.
- 유니티에서는 이를 손쉽게 구할 수 있도록 함수화가 잘 되어 있다.
2. 면적 및 부피 구하는 방법
- 아래에서 명시한 면적 및 부피 구하는 법은 인터넷에서 찾은 계산법이다.
var triangles = 메쉬변수명.triangles;
var vertices = 메쉬면수명.vertices;
//이미 계산한 폴리곤은 제외하기 위해 계산된 점들을 모아두는 임시 list
List<CalcPointInfo> points = new List<CalcPointInfo>();
double areaSum = 0.0;
double volumnSum = 0.0;
//삼각형은 3점으로 이루어져있기에 i값을 3씩 증가 한다.
//triangles에는 vertices 의 인덱스 값이 들어가 있다.
for (int i = 0; i < triangles.Length; i += 3)
{
Vector3 corner = vertices[triangles[i]];
Vector3 point1 = vertices[triangles[i + 1]];
Vector3 point2 = vertices[triangles[i + 2]];
//소수점 오차로 인해 실제 값은 0 인데 0.000000012 로 표기되면서 조건식 오류가 발생하여
//반올림하여 처리
float cornerX = (float)Math.Round(corner.x, 2);
float cornerY = (float)Math.Round(corner.y, 2);
float cornerZ = (float)Math.Round(corner.z, 2);
float point1X = (float)Math.Round(point1.x, 2);
float point1Y = (float)Math.Round(point1.y, 2);
float point1Z = (float)Math.Round(point1.z, 2);
float point2X = (float)Math.Round(point2.x, 2);
float point2Y = (float)Math.Round(point2.y, 2);
float point2Z = (float)Math.Round(point2.z, 2);
corner = new Vector3(cornerX, cornerY, cornerZ);
point1 = new Vector3(point1X, point1Y, point1Z);
point2 = new Vector3(point2X, point2Y, point2Z);
//같은 라인 선상에 있는 좌표는 건너뜀. 예를들어 세점이 모두 x 축만 다를경우 삼각형이 될수 없으므로 제외
if (cornerX == point1X && cornerX == point2X && cornerY == point1Y && cornerY == point2Y)
continue;
if (cornerX == point1X && cornerX == point2X && cornerZ == point1Z && cornerZ == point2Z)
continue;
if (cornerZ == point1Z && cornerZ == point2Z && cornerY == point1Y && cornerY == point2Y)
continue;
///대각선으로 그려진 폴리곤은 계산하지 않는다. 면적이기 때문에 오차값이 되어 버린다.
///아래의 if문은 대각선으로 그려진 폴리곤일 경우 건너뛰는 계산이다.
if ((cornerZ != point1Z && cornerX != point1X && cornerY != point1Y)
|| (cornerZ != point2Z && cornerX != point2X && cornerY != point2Y))
continue;
//3개의 같은 좌표값으로 중복계산하는걸 방지하는 코드,
int exist = (from item in points
where (corner == item.point1 || corner == item.point2 || corner == item.point3)
&& (point1 == item.point1 || point1 == item.point2 || point1 == item.point3)
&& (point2 == item.point1 || point2 == item.point2 || point2 == item.point3)
select item).Count();
if (exist > 0)
continue;
CalcPointInfo temp = new CalcPointInfo();
temp.point1 = corner;
temp.point2 = point1;
temp.point3 = point2;
points.Add(temp);
//면적
areaSum += Vector3.Cross(point1 - corner, point2 - corner).magnitude;
//부피
volumnSum += Vector3.Dot(corner, Vector3.Cross(point1, point2)) / 6.0f;
}
//면적은 sum 에서 2로 나누어야 한다.
float res = (float)(areaSum / 2.0);'Unity' 카테고리의 다른 글
| 빌드 용량 줄이기 - 1 (ft.빌드 리포트 확인) (0) | 2024.01.30 |
|---|---|
| WebGL 에서 VR 개발 (0) | 2023.12.14 |
| 폴리곤을 점으로 표현하기 (0) | 2023.12.06 |
| 키보드 및 마우스를 통한 카메라 이동, 회전 (0) | 2023.11.09 |
| UI 가 Terrain에 가려질 경우 해결법 (0) | 2023.11.07 |