2016-07-23 4 views
1

높이 맵 지형에 지형 충돌을 구현하려고하는데 다음과 같습니다. this. 이 튜토리얼은 자바 용이지만 원칙은 동일하기 때문에 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의 지형 그 부분을 마찬가지로 내가, 0.1 높이 배열의 값을 곱해야 할 수 생각 측면,하지만 그 트릭을하지 않았다. 튜토리얼

참고

getHeightOfTerrain 함수의 첫 번째 라인은 X 및 Z는 지형의 세계 위치이다

float terrainX = worldX - x; 
float terrainZ = worldZ - z; 

말한다. 이것은 지형의 위치에 상대적인 플레이어의 위치를 ​​얻는 것입니다. 번역 부분의 값으로 시도했지만 어느 것도 작동하지 않습니다. 필요하지 않으므로이 줄을 변경했습니다.

답변

1
float terrainX = worldX - x; 
float terrainZ = worldZ - z; 

그 라인은 사실 매우 필요한 지형 원점에서 항상 경우를 제외하고.

코드 리소스 (자습서)는 사용자가 지형을 어떤 방식으로도 축척을 변경하거나 회전하지 않았다고 가정합니다. xz 변수는 지형이 변환되는 경우를 처리하는 지형의 XZ 위치입니다.

이상적으로, 당신은

vec3 localPosition = inverse(model) * vec4(worldPosition, 1) 

같이합니다 (model 매트릭스는 지형에 대한 사용의 역을 사용) 공간 객체에 월드 공간에서 뭔가를 세계 위치 벡터 변환 그리고 대신 localPosition.xlocalPosition.z를 사용해야합니다 terrainXterrainZ입니다.

+0

내가 바보라고 들리는 지 모르겠지만 지역 공간 위치를 상쇄하는 변환 벡터 만 있기 때문에 어떻게 세계화 벡터를 찾을 수 있습니까?하지만 로컬 공간 위치는 알지 못합니다. 이것은 각 vertice마다 다르고 GPU는 각 vertice를 개별적으로이 translation vector로 offset하기 때문에?네가 이해한다면, 나는 무엇을 의미 하는가? @Evil Tak – Riggs

+0

지형의 왼쪽 위 모서리의 월드 공간 위치 만 필요합니다 (X, Y 및 Z 축은 각각 오른쪽, 위 및 앞으로 방향을 가리킨다 고 가정). – EvilTak

+0

모든 정점을 갖는 벡터의 첫 번째 인덱스를 확인한 다음이를 (0.0, 0.89, 0.0) + (0.0, -0.3, -15.0) = (0.0, 0.59, -15.0)로 변환하면 찾을 수 있습니다. (스케일링을하지 않으면) @Evil Tak – Riggs