내 높이 맵 지형에 대한 지형 충돌을 구현하기 위해 노력하고있어, 나는 다음있어 이 . 튜토리얼은 자바 용이지만 C ++를 사용하고 있지만 원칙은 동일하므로 문제가되지 않습니다.
시작하려면 카메라 위치를 기준으로 지형의 높이를 가져 오는 함수가 필요합니다. WorldX 및 WorldZ는 카메라의 위치 (x, z)이고 높이는 정점의 모든 높이를 포함하는 2D 배열입니다.
float HeightMap::getHeightOfTerrain(float worldX, float worldZ, float heights[][256])
{
//Image is (256 x 256)
float gridLength = 256;
float terrainLength = 256;
float terrainX = worldX;
float terrainZ = worldZ;
float gridSquareLength = terrainLength / ((float)gridLength - 1);
int gridX = (int)std::floor(terrainX / gridSquareLength);
int gridZ = (int)std::floor(terrainZ / gridSquareLength);
//Check if position is on the terrain
if (gridX >= gridLength - 1 || gridZ >= gridLength - 1 || gridX < 0 || gridZ < 0)
{
return 0;
}
//Find out where the player is on the grid square
float xCoord = std::fmod(terrainX, gridSquareLength) / gridSquareLength;
float zCoord = std::fmod(terrainZ, gridSquareLength) / gridSquareLength;
float answer = 0.0;
//Top triangle of a square else the bottom
if (xCoord <= (1 - zCoord))
{
answer = barryCentric(glm::vec3(0, heights[gridX][gridZ], 0),
glm::vec3(1, heights[gridX + 1][gridZ], 0), glm::vec3(0, heights[gridX][gridZ + 1], 1),
glm::vec2(xCoord, zCoord));
}
else
{
answer = barryCentric(glm::vec3(1, heights[gridX + 1][gridZ], 0),
glm::vec3(1, heights[gridX + 1][gridZ + 1], 1), glm::vec3(0, heights[gridX][gridZ + 1], 1),
glm::vec2(xCoord, zCoord));
}
return answer;
}
카메라가 현재 서있는 삼각형의 높이를 찾기 위해 baryCentric 보간 함수를 사용합니다.
float HeightMap::barryCentric(glm::vec3 p1, glm::vec3 p2, glm::vec3 p3, glm::vec2 pos)
{
float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z);
float l1 = ((p2.z - p3.z) * (pos.x - p3.x) + (p3.x - p2.x) * (pos.y - p3.z)) / det;
float l2 = ((p3.z - p1.z) * (pos.x - p3.x) + (p1.x - p3.x) * (pos.y - p3.z)) / det;
float l3 = 1.0f - l1 - l2;
return l1 * p1.y + l2 * p2.y + l3 * p3.y;
}
그런 다음 계산 한 높이를 사용하여 게임 중에 충돌을 확인하면됩니다.
float terrainHeight = heightMap.getHeightOfTerrain(camera.Position.x, camera.Position.z, heights);
if (camera.Position.y < terrainHeight)
{
camera.Position.y = terrainHeight;
};
이제 튜토리얼에 따르면 이것은 완벽하게 작동하지만 높이가 다소 떨어져 있고 어떤 곳에서는 작동하지 않습니다. 지형의 변환 및 크기 조정과 관련이있을 수 있다고 생각했습니다.
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0f, -0.3f, -15.0f));
model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f));
스케일링이 GPU 측 지형에 대해 해당 부분을 수행하기 때문에 heights 배열의 값에 0.1을 곱해야하지만 이것이 트릭을 수행하지는 않았습니다.
노트
튜토리얼에서 getHeightOfTerrain 함수의 첫 번째 줄은 다음과 같습니다.
float terrainX = worldX - x;
float terrainZ = worldZ - z;
여기서 x와 z는 지형의 세계 위치입니다. 이것은 지형의 위치에 상대적인 플레이어 위치를 얻기 위해 수행됩니다. 번역 부분의 값으로 시도했지만 작동하지 않습니다. 필요하지 않은 것 같아서이 라인을 변경했습니다.
float terrainX = worldX - x; float terrainZ = worldZ - z;
실제로 지형이 항상 원점에 있지 않는 한 이러한 선은 매우 필요합니다 .
코드 리소스 (튜토리얼)에서는 어떤 식 으로든 지형의 크기를 조정하거나 회전하지 않았다고 가정합니다. x
및 z
변수는 지형 번역되는 경우를 돌봐 지형의 XZ 위치입니다.
이상적으로는 월드 위치 벡터를 월드 공간에서 오브젝트 공간으로 변환해야합니다 ( model
지형에 사용 하는 행렬 의 역을 사용하여 ).
vec3 localPosition = inverse(model) * vec4(worldPosition, 1)
그리고 사용 localPosition.x
과 localPosition.z
대신 terrainX
과 terrainZ
.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다