2016-07-23 7 views
1

Я пытаюсь выполнить столкновение с рельефом местности для моей карты высоты карты, и я следую this. Учебник предназначен для Java, но я использую 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; 
} 

Чтобы найти высоту треугольника камеры в настоящее время, стоя на мы используем функцию интерполяции барицентрической.

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)); 

и что я должен умножить значения массива высот на 0,1, так как масштабирование делает эту часть для ландшафта на GPU но это не помогло.

Примечание

В учебнике первые строки в функции getHeightOfTerrain говорит

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

где х и г является мировым положением местности. Это делается для того, чтобы получить позицию игрока относительно позиции местности. Я попытался использовать значения из части перевода, но это тоже не работает. Я изменил эти строки, потому что это не кажется необходимым.

ответ

1
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.

+0

Я вижу, теперь я не знаю, звучит ли это глупо, но как я могу найти вектор Worldposition, поскольку у меня есть только вектор трансляции, который смещает локальное пространство, но я не знаю, потому что он отличается для каждой вершины, и GPU смещает каждую вершину в отдельности с помощью этого вектора перевода?Если вы понимаете, что я имею в виду? @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

 Смежные вопросы

  • Нет связанных вопросов^_^