🎨DirectX

[DX] 지면의 높이 구하기, 경사 오르기

공대 컴린이 2023. 2. 5. 16:07
728x90

🎢 지면의 높이 구하기

플레이어가 경사가 있는 땅을 올라가는것을 구현하기 위해선 바닥의 높이 값을 계산할 수 있어야 한다.

 

바닥의 높이를 구하는 데 가장 핵심적인 것은 출발지점에서 x축으로 특정 거리만큼 이동했을 때 그 이동한 비율을 계산해서 y축으로는 얼만큼 이동하는지를 구하면 된다.

예를 들어 정점 (0,0)에서 x로 1만큼 올라갔다고 하면 y로도 1만큼 올라가서 (1,1)에 위치하게 된다.

또 x로 0.5만큼 갔을때 y는 0.5만큼 갔을것이다.

이러한 원리를 이용해서 얼만큼 갔는지 비율만 알면 플레이어가 움직일 경사를 구할 수 있다.

 

플레이어가 출발지(x, y)에서 V0까지 얼마만큼 갔는지를 아는 방법은 (x - V0.x)를 구하면 된다.

여기에 V0부터 V2까지의 길이에 비례해서 (V2 - V0)를 곱하면 최종적으로 플레이어가 가로로 이동한 위치를 알 수 있다.

즉, 가로로 얼만큼 갔는지는 (V2 - V0) * (x - V0.x)를 하면 알 수 있고, 이 결과는 위치벡터 V.x가 된다.

(해당 수식이 얼마만큼 갔는지는 "비율"을 구한것)

 


❓ 그렇다면 V.y는 얼마가 될 것인가?
V.x가 이동한 비율을 적용해서 V.y가 얼마만큼 갔는지도 동일하게 구할 수 있다.

시작지점에서 한칸을 가야하는거니까 V0(시작지점) + (V2 - V0) * (x - V0.x) + (V1 - V0) * (z - V0.z) 을 구하면 된다. x와 z방향만 계산하면 된다.

만약 V0에서 V2까지의 거리가 1이 아니라 2라면 (x - V0.x)를 2만큼 나눠주면 된다. (z - V0.z)도 마찬가지. 그 길이만큼 나누어주면 크기비율은 1만큼 떨어지게 될 것이다.

따라서, 비율로 얼마만큼 갔는지를 구하면 해당 위치를 알 수 있다.

총정리

V.x = (x - V0.x) / 1.0f (한칸의 크기)
V.z = (z - V0.z) / 1.0f 
Vector3 result = V0 + (V2 - V0) * V.x + (V1 - V0) * V.z

📄 Terrain.cpp (경사면 구하는 부분만 출력)

float Terrain::GetHeight(Vector3 & position)
{
	UINT x = (UINT)position.x;
	UINT z = (UINT)position.z;

	if (x < 0 || x > width) return FLT_MIN;
	if (z < 0 || z > height) return FLT_MIN;


	UINT index[4];
	index[0] = width * z + x;
	index[1] = width * (z + 1) + x;
	index[2] = width * z + x + 1;
	index[3] = width * (z + 1) + x + 1;

	Vector3 v[4];
	for (int i = 0; i < 4; i++)
		v[i] = vertices[index[i]].Position;


	float ddx = (position.x - v[0].x) / 1.0f; // 한칸의 크기가 1이라 나누기 1
	float ddz = (position.z - v[0].z) / 1.0f;

	Vector3 result; // 최종적으로 얼마만큼 갔는지 위치

	// ddx + ddy를 더했을 때 1이 나오면 V0, V1, V2 삼각형 안에있는거고 1보다 크면 밖에 있는것
	if (ddx + ddz <= 1.0f)
		result = v[0] + (v[2] - v[0]) * ddx + (v[1] - v[0]) * ddz;
	else // 삼각형 V2, V1, V3
	{
		ddx = 1.0f - ddx;
		ddz = 1.0f - ddz;

		result = v[3] + (v[1] - v[3]) * ddx + (v[2] - v[3]) * ddz;
	}

	return result.y;
}

[ 실행 결과 ]

삼각형의 하단부로 현재 위치를 나타내고 왼쪽 상단에 높이값을 계산한 Vector3를 출력하였다.

728x90